home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / unix / wang40.zip / SA000042.TXT
Text File  |  1993-06-15  |  42KB  |  1,567 lines

  1. [ Article crossposted from alt.binaries.pictures.utilities ]
  2. [ Author was Jonathan Wang ]
  3. [ Posted on Mon, 14 Jun 1993 15:45:26 GMT ]
  4.  
  5. Some of my friends urged me to post this util for public use so that our 
  6. netters can use their time more productively, instead of wasting it by doing
  7. those time consuming downloads and reassembling of files from USENET. 
  8.  
  9.  
  10. wang.c V4.0 is planned to be a friendly USENET download-and-assemble
  11. utility, aimed at grabbing picture & audio files, zipped packages,
  12. and any other uuencoded binary posts. Instead of: 1)saving the articles
  13. from the newsreader, 2)getting rid of the news header and other trash, 
  14. 3)concatenating them into proper order, and 4)piping it to uudecode, now all 
  15. you have to do is to type "wang". Use "wang -h" for further help.
  16.  
  17. Some old USENET folks may still remember the previous wang.c versions that
  18. appeared last year. Thanks to hundreds of loyal wang.c users, I, as a 
  19. unix C newcomer,  have the courage to keep updating this util to
  20. a new version.  The new version has a greatly enhanced ability to  
  21. "understand" the subject line, and most important of all, the ability
  22. to access USENET directly without any newsreader.
  23.  
  24. wang.c is by no means meant to challenge the masterpiece pearl script 
  25. of aub, and the other existing decoders.  The objective is only to facilitate 
  26. the lazy netters like myself who are satisfied at getting the job done, 
  27. instead of getting it done perfectly. After downloading this package, 
  28. you can simply type in "make wang", and then, type "wang". Boom! it goes.
  29.  
  30. Important Notice:
  31.  
  32. By default, wang will download EVERYTHING from one newsgroup at a time 
  33. if you don't specify a range.  Take the group alt.binaries.pictures.misc 
  34. for example: it will take about half an hour to download some 150 pictures. 
  35. That means there exists the potential for filling up your disk and 
  36. slowing down your system.  Please avoid using "nohup wang &" and log
  37. off. KEEP your eyes on this monster! I advise my dear users to consult 
  38. the sysadms before using it.
  39.  
  40. I still haven't tested it thoroughly. All I can tell now is that 
  41. it will run on sysv, bsd and sunos. If you can get it compiled on
  42. any other platforms, please let me know. Yes, theoretically, it will
  43. run on any unix box which supports TCP/IP. No, it won't compile on a PC.
  44.  
  45. My sincere acknowledgement and admiration goes to Iain Lea, the author of
  46. the famous tin newreader. All my networking code has been stolen from 
  47. this genius mind and subsequently adapted to solve this problem. 
  48.  
  49. No Copyright is hereby claimed. Sell it if you can. But I do appreciate
  50. if you will mention my name.
  51.  
  52. Jonathan Wang, June, 1933.
  53.  
  54. #! /bin/sh
  55. # This is a shell archive, meaning:
  56. # 1. Remove everything above the #! /bin/sh line.
  57. # 2. Save the resulting text in a file.
  58. # 3. Execute the file with /bin/sh (not csh) to create the files:
  59. #    README
  60. #    nntplib.c
  61. #    nntplib.h
  62. #    nntpservers
  63. #    wang.c
  64. # This archive created: Mon Jun 14 11:42:28 1993
  65. export PATH; PATH=/bin:$PATH
  66. if test -f 'README'
  67. then
  68.     echo shar: will not over-write existing file "'README'"
  69. else
  70. cat << \SHAR_EOF > 'README'
  71. Some of my friends urged me to post this util for public use so that our 
  72. netters can use their time more productively, instead of wasting it by doing
  73. those time consuming downloads and reassembling of files from USENET. 
  74.  
  75.  
  76. wang.c V4.0 is planned to be a friendly USENET download-and-assemble
  77. utility, aimed at grabbing picture & audio files, zipped packages,
  78. and any other uuencoded binary posts. Instead of: 1)saving the articles
  79. from the newsreader, 2)getting rid of the news header and other trash, 
  80. 3)concatenating them into proper order, and 4)piping it to uudecode, now all 
  81. you have to do is to type "wang". Use "wang -h" for further help.
  82.  
  83. Some old USENET folks may still remember the previous wang.c versions that
  84. appeared last year. Thanks to hundreds of loyal wang.c users, I, as a 
  85. unix C newcomer,  have the courage to keep updating this util to
  86. a new version.  The new version has a greatly enhanced ability to  
  87. "understand" the subject line, and most important of all, the ability
  88. to access USENET directly without any newsreader.
  89.  
  90. wang.c is by no means meant to challenge the masterpiece pearl script 
  91. of aub, and the other existing decoders.  The objective is only to facilitate 
  92. the lazy netters like myself who are satisfied at getting the job done, 
  93. instead of getting it done perfectly. After downloading this package, 
  94. you can simply type in "make wang", and then, type "wang". Boom! it goes.
  95.  
  96. Important Notice:
  97.  
  98. By default, wang will download EVERYTHING from one newsgroup at a time 
  99. if you don't specify a range.  Take the group alt.binaries.pictures.misc 
  100. for example: it will take about half an hour to download some 150 pictures. 
  101. That means there exists the potential for filling up your disk and 
  102. slowing down your system.  Please avoid using "nohup wang &" and log
  103. off. KEEP your eyes on this monster! I advise my dear users to consult 
  104. the sysadms before using it.
  105.  
  106. I still haven't tested it thoroughly. All I can tell now is that 
  107. it will run on sysv, bsd and sunos. If you can get it compiled on
  108. any other platforms, please let me know. Yes, theoretically, it will
  109. run on any unix box which supports TCP/IP. No, it won't compile on a PC.
  110.  
  111. My sincere acknowledgement and admiration goes to Iain Lea, the author of
  112. the famous tin newreader. All my networking code has been stolen from 
  113. this genius mind and subsequently adapted to solve this problem. 
  114.  
  115. No Copyright is hereby claimed. Sell it if you can. But I do appreciate
  116. if you will mention my name.
  117.  
  118. Jonathan Wang, June, 1933.
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128. SHAR_EOF
  129. fi # end of overwriting check
  130. if test -f 'nntplib.c'
  131. then
  132.     echo shar: will not over-write existing file "'nntplib.c'"
  133. else
  134. cat << \SHAR_EOF > 'nntplib.c'
  135. /*
  136.  *  Project   : tin - a threaded Netnews reader
  137.  *  Module    : nntplib.c
  138.  *  Author    : S.Barber & I.Lea
  139.  *  Created   : 12-01-91
  140.  *  Updated   : 07-11-92
  141.  *  Notes     : NNTP client routines taken from clientlib.c 1.5.11 (10-02-91)
  142.  *  Copyright : (c) Copyright 1991-93 by Stan Barber & Iain Lea
  143.  *              Permission is hereby granted to copy, reproduce, redistribute
  144.  *              or otherwise use this software  as long as: there is no
  145.  *              monetary  profit  gained  specifically  from the use or
  146.  *              reproduction or this software, it is not  sold, rented,
  147.  *              traded or otherwise marketed, and this copyright notice
  148.  *              is included prominently in any copy made. 
  149.  */
  150.  
  151. /**************************/
  152. #define NNTP_ABLE 1
  153. #define NNTP_ONLY 1
  154.  
  155. #include <stdio.h>
  156. #include <sys/types.h>
  157. #include <errno.h>
  158. #include <ctype.h>
  159. #include "nntplib.h"
  160. /**************************/
  161. /* #include "tin.h"       */
  162. #ifdef NNTP_ONLY
  163. #    ifndef NNTP_ABLE
  164. #        define    NNTP_ABLE
  165. #    endif
  166. #endif
  167.  
  168. #ifndef CDROM_ABLE
  169.  
  170. FILE    *nntp_rd_fp = NULL;
  171. FILE    *nntp_wr_fp = NULL;
  172.  
  173. extern    int errno;
  174.  
  175. #ifdef NNTP_ABLE
  176. #    ifdef TLI
  177. #        include    <fcntl.h>
  178. #        include    <tiuser.h>
  179. #        include    <stropts.h>
  180. #        include    <sys/socket.h>
  181. #        ifdef WIN_TCP
  182. #            include    <sys/in.h>
  183. #        else
  184. #            include    <netinet/in.h>
  185. #        endif
  186. #        define    IPPORT_NNTP    ((unsigned short) 119)
  187. #        include     <netdb.h>    /* All TLI implementations may not have this */
  188. #    else
  189. #        ifdef apollo
  190. #            include </bsd4.3/usr/include/sys/socket.h>
  191. #            include </bsd4.3/usr/include/netinet/in.h>
  192. #            include </bsd4.3/usr/include/netdb.h>
  193. #        else
  194. #            include <sys/socket.h>
  195. #            include <netinet/in.h>
  196. #            ifndef EXCELAN
  197. #                include <netdb.h>
  198. #            endif
  199. #        endif
  200. #    endif /* !TLI */
  201.  
  202. #    ifndef BSD
  203. #        define    index(a,b)    strchr(a,b)
  204. #        define    bcopy(a,b,c)    memcpy(b,a,c)
  205. #        define    bzero(a,b)    memset(a,'\0',b)
  206. #    endif
  207.  
  208. #    ifdef EXCELAN
  209. #        if __STDC__
  210.             int connect (int, struct sockaddr *);
  211.             unsigned short htons (unsigned short);
  212.             unsigned long rhost (char **);
  213.             int rresvport (int);
  214.             int socket (int, struct sockproto *, struct sockaddr_in *, int);
  215. #        endif
  216. #    endif
  217.  
  218. #    ifdef DECNET
  219. #        include <netdnet/dn.h>
  220. #        include <netdnet/dnetdb.h>
  221. #    endif
  222.  
  223. #endif /* NNTP_ABLE */
  224.  
  225. /*
  226.  * getserverbyfile    Get the name of a server from a named file.
  227.  *            Handle white space and comments.
  228.  *            Use NNTPSERVER environment variable if set.
  229.  *
  230.  *    Parameters:    "file" is the name of the file to read.
  231.  *
  232.  *    Returns:    Pointer to static data area containing the
  233.  *            first non-ws/comment line in the file.
  234.  *            NULL on error (or lack of entry in file).
  235.  *
  236.  *    Side effects:    None.
  237.  */
  238.  
  239. char *getserverbyfile (file)
  240.     char    *file;
  241. {
  242. #ifdef NNTP_ABLE
  243.     register FILE    *fp;
  244.     register char    *cp;
  245.     static char    buf[256];
  246.  
  247.     if (cp = (char *) getenv ("NNTPSERVER")) {
  248.         (void) strcpy (buf, cp);
  249.         return (buf);
  250.     }
  251.  
  252.     if (file == NULL)
  253.         return (NULL);
  254.  
  255.     if ((fp = fopen (file, "r")) == NULL)
  256.         return (NULL);
  257.  
  258.     while (fgets (buf, sizeof (buf), fp) != NULL) {
  259.         if (*buf == '\n' || *buf == '#') {
  260.             continue;
  261.         }
  262.         cp = (char *) index(buf, '\n');
  263.         if (cp) {
  264.             *cp = '\0';
  265.         }
  266.         (void) fclose (fp);
  267.         return (buf);
  268.     }
  269.  
  270.     (void) fclose (fp);
  271. #endif /* NNTP_ABLE */
  272.     return (NULL);             /* No entry */
  273. }
  274.  
  275. /*
  276.  * server_init  Get a connection to the remote server.
  277.  *
  278.  *    Parameters:    "machine" is the machine to connect to.
  279.  *            "service" is the service to connect to on the machine.
  280.  *            "port" is the servive port to connect to.
  281.  *
  282.  *    Returns:    -1 on error
  283.  *            server's initial response code on success.
  284.  *
  285.  *    Side effects:    Connects to server.
  286.  *            "nntp_rd_fp" and "nntp_wr_fp" are fp's
  287.  *            for reading and writing to server.
  288.  */
  289.  
  290. int server_init (machine, service, port)
  291.     char    *machine;
  292.     char    *service;
  293.     unsigned short port;
  294. {
  295. #ifdef NNTP_ABLE
  296.     int    sockt_rd, sockt_wr;
  297.     char    line[256];
  298. #ifdef DECNET
  299.     char    *cp;
  300.  
  301.     cp = (char *) index(machine, ':');
  302.  
  303.     if (cp && cp[1] == ':') {
  304.         *cp = '\0';
  305.         sockt_rd = get_dnet_socket (machine, service);
  306.     } else {
  307.         sockt_rd = get_tcp_socket (machine, service, port);
  308.     }
  309. #else
  310.     sockt_rd = get_tcp_socket (machine, service, port);
  311. #endif
  312.  
  313.     if (sockt_rd < 0)
  314.         return (-1);
  315.  
  316.     /*
  317.      * Now we'll make file pointers (i.e., buffered I/O) out of
  318.      * the socket file descriptor.  Note that we can't just
  319.      * open a fp for reading and writing -- we have to open
  320.      * up two separate fp's, one for reading, one for writing.
  321.      */
  322.  
  323.     if ((nntp_rd_fp = (FILE *) fdopen (sockt_rd, "r")) == NULL) {
  324.         perror ("server_init: fdopen #1");
  325.         return (-1);
  326.     }
  327.  
  328.     sockt_wr = dup (sockt_rd);
  329. #ifdef TLI
  330.     if (t_sync (sockt_rd) < 0) {    /* Sync up new fd with TLI */
  331.             t_error ("server_init: t_sync");
  332.         nntp_rd_fp = NULL;        /* from above */
  333.         return (-1);
  334.     }
  335. #endif
  336.     if ((nntp_wr_fp = (FILE *) fdopen (sockt_wr, "w")) == NULL) {
  337.         perror ("server_init: fdopen #2");
  338.         nntp_rd_fp = NULL;        /* from above */
  339.         return (-1);
  340.     }
  341.  
  342.     /*
  343.      * Now get the server's signon message
  344.      */
  345.  
  346.     (void) get_server (line, sizeof (line));
  347.     return (atoi (line));
  348. #else
  349.     return (-1);
  350. #endif /* NNTP_ABLE */
  351. }
  352.  
  353. /*
  354.  * get_tcp_socket -- get us a socket connected to the specified server.
  355.  *
  356.  *    Parameters:    "machine" is the machine the server is running on.
  357.  *            "service" is the service to connect to on the server.
  358.  *            "port" is the port to connect to on the server.
  359.  *
  360.  *    Returns:    Socket connected to the server if
  361.  *            all is ok, else -1 on error.
  362.  *
  363.  *    Side effects:    Connects to server.
  364.  *
  365.  *    Errors:        Printed via perror.
  366.  */
  367.  
  368. int get_tcp_socket (machine, service, port)
  369.     char    *machine;    /* remote host */
  370.     char    *service;    /* nttp/smtp etc. */
  371.     unsigned short port;    /* tcp port number */
  372. {
  373. #ifdef NNTP_ABLE
  374.     int    s = -1;
  375.     struct    sockaddr_in sin;
  376. #ifdef TLI 
  377.     struct    hostent *gethostbyname (), *hp;
  378.     struct    t_call    *callptr;
  379.  
  380.     /*
  381.      * Create a TCP transport endpoint.
  382.      */
  383.     if ((s = t_open ("/dev/tcp", O_RDWR, (struct t_info*) 0)) < 0){
  384.         t_error ("t_open: can't t_open /dev/tcp");
  385.         return (-1);
  386.     }
  387.     if (t_bind (s, (struct t_bind *) 0, (struct t_bind *) 0) < 0) {
  388.            t_error ("t_bind");
  389.         t_close (s);
  390.         return (-1);
  391.     }
  392.     bzero((char *) &sin, sizeof (sin));    
  393.     sin.sin_family = AF_INET;
  394.     sin.sin_port = htons (port);
  395.     if (!isdigit(*machine) ||
  396.         (long)(sin.sin_addr.s_addr = inet_addr (machine)) == -1) {
  397.         if((hp = gethostbyname (machine)) == NULL) {
  398.             fprintf (stderr, "gethostbyname: %s: host unknown\n", machine);
  399.             t_close (s);
  400.             return (-1);
  401.         }
  402.         bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
  403.     }
  404.     
  405.     /*
  406.      * Allocate a t_call structure and initialize it.
  407.      * Let t_alloc() initialize the addr structure of the t_call structure.
  408.      */
  409.     if ((callptr = (struct t_call *) t_alloc (s,T_CALL,T_ADDR)) == NULL){
  410.         t_error ("t_alloc");
  411.         t_close (s);
  412.         return (-1);
  413.     }
  414.  
  415.     callptr->addr.maxlen = sizeof (sin);
  416.     callptr->addr.len = sizeof (sin);
  417.     callptr->addr.buf = (char *) &sin;
  418.     callptr->opt.len = 0;            /* no options */
  419.     callptr->udata.len = 0;            /* no user data with connect */
  420.  
  421.     /*
  422.      * Connect to the server.
  423.      */
  424.     if (t_connect (s, callptr, (struct t_call *) 0) < 0) {
  425.         t_error ("t_connect");
  426.         t_close (s);
  427.         return (-1);
  428.     }
  429.  
  430.     /*
  431.      * Now replace the timod module with the tirdwr module so that
  432.      * standard read() and write() system calls can be used on the
  433.      * descriptor.
  434.      */
  435.  
  436.     if (ioctl (s,  I_POP,  (char *) 0) < 0) {
  437.         perror ("I_POP(timod)");
  438.         t_close (s);
  439.         return (-1);
  440.     }
  441.  
  442.     if (ioctl (s,  I_PUSH, "tirdwr") < 0) {
  443.         perror ("I_PUSH(tirdwr)");
  444.         t_close (s);
  445.         return (-1);
  446.     }
  447.     
  448. #else /* !TLI */
  449. #ifndef EXCELAN
  450.     struct    servent *getservbyname(), *sp;
  451.     struct    hostent *gethostbyname(), *hp;
  452. #ifdef h_addr
  453.     int    x = 0;
  454.     register char **cp;
  455.     static char *alist[1];
  456. #endif /* h_addr */
  457.     unsigned long inet_addr();
  458.     static struct hostent def;
  459.     static struct in_addr defaddr;
  460.     static char namebuf[256];
  461.  
  462.     if ((sp = getservbyname (service, "tcp")) ==  NULL) {
  463.         fprintf (stderr, "%s/tcp: Unknown service.\n", service);
  464.         return (-1);
  465.     }
  466.     /* If not a raw ip address, try nameserver */
  467.     if (!isdigit(*machine) ||
  468.         (long)(defaddr.s_addr = inet_addr (machine)) == -1)
  469.         hp = gethostbyname (machine);
  470.     else {
  471.         /* Raw ip address, fake  */
  472.         (void) strcpy (namebuf, machine);
  473.         def.h_name = namebuf;
  474. #ifdef h_addr
  475.         def.h_addr_list = alist;
  476. #endif
  477.         def.h_addr = (char *) &defaddr;
  478.         def.h_length = sizeof (struct in_addr);
  479.         def.h_addrtype = AF_INET;
  480.         def.h_aliases = 0;
  481.         hp = &def;
  482.     }
  483.     if (hp == NULL) {
  484.         fprintf (stderr, "\n%s: Unknown host.\n", machine);
  485.         return (-1);
  486.     }
  487.  
  488.     bzero((char *) &sin, sizeof (sin));
  489.     sin.sin_family = hp->h_addrtype;
  490.     sin.sin_port = sp->s_port;
  491. #else /* EXCELAN */
  492.     bzero((char *) &sin, sizeof (sin));
  493.     sin.sin_family = AF_INET;
  494. #endif /* EXCELAN */
  495.  
  496.     /*
  497.      * The following is kinda gross.  The name server under 4.3
  498.      * returns a list of addresses, each of which should be tried
  499.      * in turn if the previous one fails.  However, 4.2 hostent
  500.      * structure doesn't have this list of addresses.
  501.      * Under 4.3, h_addr is a #define to h_addr_list[0].
  502.      * We use this to figure out whether to include the NS specific
  503.      * code...
  504.      */
  505.  
  506. #ifdef h_addr
  507.     /*
  508.      * get a socket and initiate connection -- use multiple addresses
  509.      */
  510.  
  511.     for (cp = hp->h_addr_list; cp && *cp; cp++) {
  512.         s = socket (hp->h_addrtype, SOCK_STREAM, 0);
  513.         if (s < 0) {
  514.             perror ("socket");
  515.             return (-1);
  516.         }
  517.         bcopy(*cp, (char *) &sin.sin_addr, hp->h_length);
  518.         
  519.         if (x < 0) {
  520.             fprintf (stderr, "Trying %s", (char *) inet_ntoa (sin.sin_addr));
  521.         }
  522.         x = connect (s, (struct sockaddr *) &sin, sizeof (sin));
  523.         if (x == 0) {
  524.             break;
  525.         }
  526.         fprintf (stderr, "\nConnection to %s: ", (char *) inet_ntoa (sin.sin_addr));
  527.         perror ("");
  528.         (void) close (s);
  529.     }
  530.     if (x < 0) {
  531.         fprintf (stderr, "Giving up...\n");
  532.         return (-1);
  533.     }
  534. #else    /* no name server */
  535. #ifdef EXCELAN
  536.     if ((s = socket (SOCK_STREAM,(struct sockproto *)NULL,&sin,SO_KEEPALIVE)) < 0) {
  537.         /* Get the socket */
  538.         perror ("socket");
  539.         return (-1);
  540.     }
  541.     bzero((char *) &sin, sizeof (sin));
  542.     sin.sin_family = AF_INET;
  543.     sin.sin_port = htons (IPPORT_NNTP);
  544.     /* set up addr for the connect */
  545.  
  546.     if ((sin.sin_addr.s_addr = rhost (&machine)) == -1) {
  547.         fprintf (stderr, "\n%s: Unknown host.\n", machine);
  548.         return (-1);
  549.     }
  550.     /* And then connect */
  551.  
  552.     if (connect (s, (struct sockaddr *)&sin) < 0) {
  553.         perror ("connect");
  554.         (void) close (s);
  555.         return (-1);
  556.     }
  557. #else /* not EXCELAN */
  558.     if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
  559.         perror ("socket");
  560.         return (-1);
  561.     }
  562.  
  563.     /* And then connect */
  564.  
  565.     bcopy (hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
  566.     if (connect (s, (struct sockaddr *) &sin, sizeof (sin)) < 0) {
  567.         perror ("connect");
  568.         (void) close (s);
  569.         return (-1);
  570.     }
  571.  
  572. #endif /* !EXCELAN */
  573. #endif /* !h_addr */
  574. #endif /* !TLI */
  575.     return (s);
  576. #else
  577.     return (-1);
  578. #endif /* NNTP_ABLE */
  579. }
  580.  
  581. #ifdef DECNET
  582. /*
  583.  * get_dnet_socket -- get us a socket connected to the server.
  584.  *
  585.  *    Parameters:    "machine" is the machine the server is running on.
  586.  *            "service" is the name of the service to connect to.
  587.  *
  588.  *    Returns:    Socket connected to the news server if
  589.  *            all is ok, else -1 on error.
  590.  *
  591.  *    Side effects:    Connects to server.
  592.  *
  593.  *    Errors:        Printed via nerror.
  594.  */
  595.  
  596. int get_dnet_socket (machine, service)
  597.     char    *machine;
  598.     char    *service;
  599. {
  600. #ifdef NNTP_ABLE
  601.     int    s, area, node;
  602.     struct    sockaddr_dn sdn;
  603.     struct    nodeent *getnodebyname(), *np;
  604.  
  605.     bzero((char *) &sdn, sizeof (sdn));
  606.  
  607.     switch (s = sscanf (machine, "%d%*[.]%d", &area, &node)) {
  608.         case 1: 
  609.             node = area;
  610.             area = 0;
  611.         case 2: 
  612.             node += area*1024;
  613.             sdn.sdn_add.a_len = 2;
  614.             sdn.sdn_family = AF_DECnet;
  615.             sdn.sdn_add.a_addr[0] = node % 256;
  616.             sdn.sdn_add.a_addr[1] = node / 256;
  617.             break;
  618.         default:
  619.             if ((np = getnodebyname (machine)) == NULL) {
  620.                 fprintf (stderr, "%s: Unknown host.\n", machine);
  621.                 return (-1);
  622.             } else {
  623.                 bcopy(np->n_addr, (char *) sdn.sdn_add.a_addr, np->n_length);
  624.                 sdn.sdn_add.a_len = np->n_length;
  625.                 sdn.sdn_family = np->n_addrtype;
  626.             }
  627.             break;
  628.     }
  629.     sdn.sdn_objnum = 0;
  630.     sdn.sdn_flags = 0;
  631.     sdn.sdn_objnamel = strlen ("NNTP");
  632.     bcopy("NNTP", &sdn.sdn_objname[0], sdn.sdn_objnamel);
  633.  
  634.     if ((s = socket (AF_DECnet, SOCK_STREAM, 0)) < 0) {
  635.         nerror ("socket");
  636.         return (-1);
  637.     }
  638.  
  639.     /* And then connect */
  640.  
  641.     if (connect (s, (struct sockaddr *) &sdn, sizeof (sdn)) < 0) {
  642.         nerror ("connect");
  643.         close (s);
  644.         return (-1);
  645.     }
  646.  
  647.     return (s);
  648. #else
  649.     return (-1);
  650. #endif /* NNTP_ABLE */
  651. }
  652. #endif
  653.  
  654. /*
  655.  * handle_server_response
  656.  *
  657.  *    Print some informative messages based on the server's initial
  658.  *    response code.  This is here so inews, rn, etc. can share
  659.  *    the code.
  660.  *
  661.  *    Parameters:    "response" is the response code which the
  662.  *            server sent us, presumably from "server_init",
  663.  *            above.
  664.  *            "nntpserver" is the news server we got the
  665.  *            response code from.
  666.  *
  667.  *    Returns:    -1 if the error is fatal (and we should exit).
  668.  *            0 otherwise.
  669.  *
  670.  *    Side effects:    None.
  671.  */
  672.  
  673. int handle_server_response (response, nntpserver)
  674.     int    response;
  675.     char    *nntpserver;
  676. {
  677. #ifdef NNTP_ABLE
  678.     switch (response) {
  679.         case OK_NOPOST:        /* fall through */
  680.                 printf ("NOTE: This machine does not have permission to post articles.\n");
  681.             printf ("      Please don't waste your time trying.\n\n");
  682.  
  683.         case OK_CANPOST:
  684.             return (0);
  685.             break;
  686.  
  687.         case ERR_ACCESS:
  688.             printf ("This machine does not have permission to use the %s news server.\n", nntpserver);
  689.             return (-1);
  690.             break;
  691.  
  692.         default:
  693.             printf ("Unexpected response code from %s news server: %d\n",
  694.                 nntpserver, response);
  695.             return (-1);
  696.             break;
  697.     }
  698.     /*NOTREACHED*/
  699. #else
  700.     return (-1);
  701. #endif /* NNTP_ABLE */
  702. }
  703.  
  704. /*
  705.  * put_server -- send a line of text to the server, terminating it
  706.  * with CR and LF, as per ARPA standard.
  707.  *
  708.  *    Parameters:    "string" is the string to be sent to the
  709.  *            server.
  710.  *
  711.  *    Returns:    Nothing.
  712.  *
  713.  *    Side effects:    Talks to the server.
  714.  *
  715.  *    Note:    This routine flushes the buffer each time
  716.  *            it is called.  For large transmissions
  717.  *            (i.e., posting news) don't use it.  Instead,
  718.  *            do the fprintf's yourself, and then a final
  719.  *            fflush.
  720.  */
  721.  
  722. void put_server (string)
  723.     char *string;
  724. {
  725. #ifdef NNTP_ABLE
  726.     fprintf (nntp_wr_fp, "%s\r\n", string);
  727.     (void) fflush (nntp_wr_fp);
  728. #endif /* NNTP_ABLE */
  729. }
  730.  
  731. /*
  732.  * get_server -- get a line of text from the server.  Strips
  733.  * CR's and LF's.
  734.  *
  735.  *    Parameters:    "string" has the buffer space for the
  736.  *            line received.
  737.  *            "size" is the size of the buffer.
  738.  *
  739.  *    Returns:    -1 on error, 0 otherwise.
  740.  *
  741.  *    Side effects:    Talks to server, changes contents of "string".
  742.  */
  743.  
  744. int get_server (string, size)
  745.     char    *string;
  746.     int    size;
  747. {
  748. #ifdef NNTP_ABLE
  749.     register char *cp;
  750.  
  751.     while (fgets (string, size, nntp_rd_fp) == NULL) {
  752.         if (errno != EINTR) {
  753.             return (-1);
  754.         }    
  755.     }
  756.  
  757.     if ((cp = (char *) index(string, '\r')) != NULL) {
  758.         *cp = '\0';
  759.     } else if ((cp = (char *) index(string, '\n')) != NULL) {
  760.         *cp = '\0';
  761.     }
  762.  
  763.     return (0);
  764. #else
  765.     return (-1);
  766. #endif /* NNTP_ABLE */
  767. }
  768.  
  769. /*
  770.  * close_server -- close the connection to the server, after sending
  771.  *        the "quit" command.
  772.  *
  773.  *    Parameters:    None.
  774.  *
  775.  *    Returns:    Nothing.
  776.  *
  777.  *    Side effects:    Closes the connection with the server.
  778.  *            You can't use "put_server" or "get_server"
  779.  *            after this routine is called.
  780.  */
  781.  
  782. void close_server ()
  783. {
  784. #ifdef NNTP_ABLE
  785.     char    ser_line[256];
  786.  
  787.     if (nntp_wr_fp == NULL || nntp_rd_fp == NULL)
  788.         return;
  789.  
  790.     put_server ("QUIT");
  791.     (void) get_server (ser_line, sizeof (ser_line));
  792.  
  793.     (void) fclose (nntp_wr_fp);
  794.     (void) fclose (nntp_rd_fp);
  795. #endif /* NNTP_ABLE */
  796. }
  797.  
  798. #endif /* CDROM_ABLE */
  799.  
  800. SHAR_EOF
  801. fi # end of overwriting check
  802. if test -f 'nntplib.h'
  803. then
  804.     echo shar: will not over-write existing file "'nntplib.h'"
  805. else
  806. cat << \SHAR_EOF > 'nntplib.h'
  807. /*
  808.  *  Project   : tin - a threaded Netnews reader
  809.  *  Module    : nntplib.h
  810.  *  Author    : I.Lea
  811.  *  Created   : 01-04-91
  812.  *  Updated   : 18-11-92
  813.  *  Notes     : nntp.h 1.5.11/1.6 with extensions for tin & CD-ROM
  814.  *  Copyright : You may  freely  copy or  redistribute  this software,
  815.  *              so  long as there is no profit made from its use, sale
  816.  *              trade or  reproduction.  You may not change this copy-
  817.  *              right notice, and it must be included in any copy made
  818.  */
  819.  
  820. #ifndef    NNTP_SERVER_FILE
  821. #    define    NNTP_SERVER_FILE    "/etc/nntpserver"
  822. #endif
  823.  
  824. #define    NNTP_TCP_NAME    "nntp"
  825. #define    NNTP_TCP_PORT    ((unsigned short) 119)
  826.  
  827. #ifndef    SMTP_SERVER_FILE
  828. #    define    SMTP_SERVER_FILE    "/etc/smtpserver"
  829. #endif
  830.  
  831. #define    SMTP_TCP_NAME    "smtp"
  832. #define    SMTP_TCP_PORT    ((unsigned short) 25)
  833.  
  834. /*
  835.  *  External routine declarations
  836.  */
  837.  
  838. extern char *getserverbyfile();
  839. /* extern int server_init(); */
  840. extern int get_tcp_socket();
  841. extern int handle_server_response();
  842. extern void put_server();
  843. extern int get_server();
  844. extern void close_server();
  845.  
  846. /*
  847.  *  External file descriptors for the server connection
  848.  */
  849.  
  850. extern FILE *nntp_wr_fp;
  851.  
  852. /*
  853.  * Response codes for NNTP server
  854.  *
  855.  * @(#)Header: nntp.h,v 1.81 92/03/12 02:08:31 sob Exp $
  856.  *
  857.  * First digit:
  858.  *
  859.  *    1xx    Informative message
  860.  *    2xx    Command ok
  861.  *    3xx    Command ok so far, continue
  862.  *    4xx    Command was correct, but couldn't be performed
  863.  *        for some specified reason.
  864.  *    5xx    Command unimplemented, incorrect, or a
  865.  *        program error has occured.
  866.  *
  867.  * Second digit:
  868.  *
  869.  *    x0x    Connection, setup, miscellaneous
  870.  *    x1x    Newsgroup selection
  871.  *    x2x    Article selection
  872.  *    x3x    Distribution
  873.  *    x4x    Posting
  874.  */
  875.  
  876. #define    CHAR_INF    '1'
  877. #define    CHAR_OK        '2'
  878. #define    CHAR_CONT    '3'
  879. #define    CHAR_ERR    '4'
  880. #define    CHAR_FATAL    '5'
  881.  
  882. #define    INF_HELP        100    /* Help text on way */
  883. #define    INF_AUTH        180    /* Authorization capabilities */
  884. #define    INF_DEBUG        199    /* Debug output */
  885.  
  886. #define    OK_CANPOST        200    /* Hello; you can post */
  887. #define    OK_NOPOST        201    /* Hello; you can't post */
  888. #define    OK_SLAVE        202    /* Slave status noted */
  889. #define    OK_GOODBYE        205    /* Closing connection */
  890. #define    OK_GROUP        211    /* Group selected */
  891. #define    OK_GROUPS        215    /* Newsgroups follow */
  892.  
  893. #define OK_XMOTD        217    /* News motd follows */
  894. #define OK_XINDEX        218    /* Tin style index follows */
  895. #define OK_XOVERVIEW        219    /* .overview style index follows */
  896.  
  897. #define    OK_ARTICLE        220    /* Article (head & body) follows */
  898. #define    OK_HEAD            221    /* Head follows */
  899. #define    OK_BODY            222    /* Body follows */
  900. #define    OK_NOTEXT        223    /* No text sent -- stat, next, last */
  901. #define    OK_NEWNEWS        230    /* New articles by message-id follow */
  902. #define    OK_NEWGROUPS        231    /* New newsgroups follow */
  903. #define    OK_XFERED        235    /* Article transferred successfully */
  904. #define    OK_POSTED        240    /* Article posted successfully */
  905. #define    OK_AUTHSYS        280    /* Authorization system ok */
  906. #define    OK_AUTH            281    /* Authorization (user/pass) ok */
  907. #define OK_BIN            282    /* binary data follows */
  908. #define OK_SPLIST        283    /* spooldir list follows */
  909. #define OK_SPSWITCH        284    /* Switching to a different spooldir */
  910. #define OK_SPNOCHANGE        285    /* Still using same spooldir */
  911. #define OK_SPLDIRCUR        286    /* Current spooldir */
  912. #define OK_SPLDIRAVL        287    /* Available spooldir */
  913. #define OK_SPLDIRERR        288    /* Unavailable spooldir or invalid entry */
  914.  
  915. #define CONT_XFER        335    /* Continue to send article */
  916. #define    CONT_POST        340    /* Continue to post article */
  917. #define    NEED_AUTHINFO        380    /* authorization is required */
  918. #define    NEED_AUTHDATA        381    /* <type> authorization data required */
  919.  
  920. #define    ERR_GOODBYE        400    /* Have to hang up for some reason */
  921. #define    ERR_NOGROUP        411    /* No such newsgroup */
  922. #define    ERR_NCING        412    /* Not currently in newsgroup */
  923.  
  924. #define ERR_XMOTD        417    /* No news motd file */
  925. #define ERR_XINDEX        418    /* No tin index for this group */
  926. #define ERR_XOVERVIEW        419    /* No .overview index for this group */
  927.  
  928. #define    ERR_NOCRNT        420    /* No current article selected */
  929. #define    ERR_NONEXT        421    /* No next article in this group */
  930. #define    ERR_NOPREV        422    /* No previous article in this group */
  931. #define    ERR_NOARTIG        423    /* No such article in this group */
  932. #define ERR_NOART        430    /* No such article at all */
  933. #define ERR_GOTIT        435    /* Already got that article, don't send */
  934. #define ERR_XFERFAIL        436    /* Transfer failed */
  935. #define    ERR_XFERRJCT        437    /* Article rejected, don't resend */
  936. #define    ERR_NOPOST        440    /* Posting not allowed */
  937. #define    ERR_POSTFAIL        441    /* Posting failed */
  938. #define    ERR_NOAUTH        480    /* authorization required for command */
  939. #define    ERR_AUTHSYS        481    /* Authorization system invalid */
  940. #define    ERR_AUTHREJ        482    /* Authorization data rejected */
  941. #define ERR_INVALIAS        483    /* Invalid alias on spooldir cmd */
  942. #define ERR_INVNOSPDIR        484    /* No spooldir file found */
  943.  
  944. #define    ERR_COMMAND        500    /* Command not recognized */
  945. #define    ERR_CMDSYN        501    /* Command syntax error */
  946. #define    ERR_ACCESS        502    /* Access to server denied */
  947. #define ERR_FAULT        503    /* Program fault, command not performed */
  948. #define    ERR_AUTHBAD        580    /* Authorization Failed */
  949.     
  950. /*
  951.  * RFC 977 defines this; don't change it.
  952.  */
  953.  
  954. #define    NNTP_STRLEN        512
  955. SHAR_EOF
  956. fi # end of overwriting check
  957. if test -f 'nntpservers'
  958. then
  959.     echo shar: will not over-write existing file "'nntpservers'"
  960. else
  961. cat << \SHAR_EOF > 'nntpservers'
  962. /**********************************************************/
  963. /* This is a short list of public accessable NNTP servers */
  964. /*  by Jonathan Wang, May 13, 1993               */
  965. /*    wang@astro.temple.edu                  */
  966. /*                              */
  967. /* 200: Posting OK;  201: No posting                      */
  968. /*                              */
  969. /* Note: I DO NOT have the authorization to use them      */
  970. /*       Using these services at your own risk            */
  971. /**********************************************************/
  972.  
  973. aardvark.ucs.uoknor.edu 201
  974. ac.dal.ca 201
  975. acad.drake.edu 201
  976. acavax.lynchburg.edu 200
  977. aqueous.ml.csiro.AU 200
  978. bert.eecs.uic.edu 201
  979. blaze.trentu.ca 201
  980. bunyip.cc.uq.oz.au 201
  981. buzzard.eecs.umich.edu 200
  982. cc.ntnu.edu.tw 200
  983. cc.usu.edu 201
  984. ccds3.ntu.edu.tw 200
  985. ccnews.nctu.edu.tw 200
  986. ccsvax.sfasu.edu 200
  987. ccvax.ucd.ie 200
  988. cronkite.ocis.temple.edu 200
  989. crux.rp.CSIRO.AU 200
  990. csc.canberra.edu.au 201
  991. csun.edu 200
  992. cv3.cv.nrao.edu 200
  993. dec8.ncku.edu.tw 200
  994. desire.wright.edu 200
  995. donau.et.tudelft.nl 200
  996. emba-news.uvm.edu 201
  997. embl-heidelberg.de 200
  998. fac.cabot.nf.ca 200
  999. falcon.aamrl.wpafb.af.mil 200
  1000. fang.dsto.gov.au 200
  1001. faraday.ece.cmu.edu 200
  1002. fission.dt.wdc.com 200
  1003. flash.pax.tpa.com.au 200
  1004. foxhound.dsto.gov.au 200
  1005. gaia.ucs.orst.edu 201
  1006. gmuvax.gmu.edu 201
  1007. gneiss.bmr.gov.au 200
  1008. grumpy.symantec.com 200
  1009. guardian.up.edu 201
  1010. hack.dragoman.com 201
  1011. hkuxb.hku.hk 201
  1012. hmcvax.claremont.edu 201
  1013. inca.comlab.ox.ac.uk 201
  1014. informatik.uni-koblenz.de 200
  1015. iris.resntl.bhp.com.au 201
  1016. iti.gov.sg 201
  1017. jabaru.cec.edu.au 200
  1018. jvnc.net 201
  1019. lambda.msfc.nasa.gov 201
  1020. SHAR_EOF
  1021. fi # end of overwriting check
  1022. if test -f 'wang.c'
  1023. then
  1024.     echo shar: will not over-write existing file "'wang.c'"
  1025. else
  1026. cat << \SHAR_EOF > 'wang.c'
  1027. /******************************************************************/
  1028. /* wang.c version 4.0                                             */
  1029. /*  by Jonathan Wang, May 20, 1993                                */
  1030. /*     wang@astro.ocis.temple.edu                                 */
  1031. /*                                                                */
  1032. /* USENET binary files download and  assemble utility             */
  1033. /* type wang -h for help                                          */
  1034. /******************************************************************/
  1035.  
  1036. char nntpserver[255]= "128.8.10.5"; /*umd5.umd.edu*/
  1037. char newsgroup[255]=  "alt.binaries.pictures.misc";
  1038. int  index_start=0;
  1039. int  index_end=0;
  1040.  
  1041. #include <stdio.h>
  1042. #include <string.h>
  1043. #include <fcntl.h>
  1044.  
  1045. #include "nntplib.c"
  1046.  
  1047. #define MAXFILES 2048
  1048.  
  1049. struct superblock
  1050. {
  1051.   char Filename[255];
  1052.   int  Part;
  1053.   int  Parts;
  1054.   int  Article;
  1055. /*char Newsgroup[255]; */
  1056. }                  Filereg[MAXFILES];
  1057.  
  1058.  
  1059. #define LEN 255
  1060. char line[LEN], buf[LEN];
  1061. int  filecount=0;
  1062.  
  1063. struct superblock nextfilereg();
  1064.  
  1065. /*************************************************************/
  1066. main(argc, argv)
  1067. int  argc;
  1068. char *argv[];
  1069. {
  1070. ArgumentProcess(argc, argv);
  1071.  
  1072. puts("Warning: This program may generate up to 250 picture files.");
  1073. puts("         i.e., appox. 20M disk space will be used.");
  1074. puts("Please make appropriate preparation and inform your sysadm.");
  1075. puts("FYI: The priority is lowered to +10\n"); 
  1076. nice(10); /* don't wanna sysadm freak out */
  1077.  
  1078.  
  1079. puts("setting up connection ...");
  1080. server_init(nntpserver, "nntp", 119);
  1081.  
  1082. SubjectAnalysis();
  1083. Retrieve();
  1084.  
  1085. close_server();
  1086. }/* end of main */
  1087.  
  1088. /**********************************************************/
  1089. ArgumentProcess(argc, argv)
  1090. int  argc;
  1091. char *argv[];
  1092. {
  1093. int i;
  1094.  
  1095. for (i=1; i<argc; i++)
  1096.   {
  1097.     if ( strcmp(argv[i],"-s") == 0 )
  1098.       strcpy(nntpserver,argv[i+1]);
  1099.     else if ( strcmp(argv[i], "-g") == 0 )
  1100.       strcpy(newsgroup,argv[i+1]);
  1101.     else if ( strcmp(argv[i], "-n") == 0 )
  1102.       {
  1103.     index_start = atoi(argv[i+1]);
  1104.     index_end   = atoi(argv[i+3]);
  1105.       }
  1106.     else if ( strcmp(argv[i], "-h") == 0 )
  1107.       {
  1108.     printf("Usage: %s [-s nntpServer] [-g newsGroup] [-n start - end]\n\n",
  1109.          argv[0]);
  1110.     printf("-s nntpServer\tThe news server. The default server is:\n\
  1111. \t\t%s\n\
  1112. \tYou are encouraged to use your local news server\n\
  1113. \tso as to cut the the transmission time and \n\
  1114. \tthe network load.\n",nntpserver);
  1115.     printf("-g newsGroup\tThe newsgroup. The default newsgroup is:\n\
  1116. \t\t%s\n",newsgroup);
  1117.     printf("-n start - end\tStart and Ending number of Articles.\n\
  1118. \tThe default is all the available articles.\n\
  1119. \tPlease refer to the available article numbers\n\
  1120. \teach time the program runs.\n\
  1121. \tYou are strongly recommended to use this option\n\
  1122. \tto control the limit of incoming articles.\n\n\
  1123. Please be aware that the space beween each identifier is required.\n");
  1124.     exit(0);
  1125.       }
  1126.   } /* end of for */
  1127.  
  1128. } /* end of ArgumentProcess */
  1129. /**********************************************************/
  1130. /* basically same as the old wang.c                       */
  1131. /* instead of reading from a file, now we read from USENET*/
  1132. Retrieve()
  1133. {
  1134. struct superblock reg;
  1135.  
  1136. reg = nextfilereg();
  1137. while (*(reg.Filename)) /* not empty */
  1138.   {
  1139.     printf("\nDecoding file %s (Article %d)...",
  1140.        reg.Filename, reg.Article);
  1141.     if (MakeOnePicture(reg)) /* successful? */
  1142.       printf("\tDone.");
  1143.     reg = nextfilereg();
  1144.   } /* end of while */
  1145.  
  1146. printf("\n==================== DONE ====================\n");
  1147.     
  1148. } /* end of Retrieve */
  1149.  
  1150. /***************************************/
  1151. MakeOnePicture(reg)
  1152. struct superblock reg;
  1153. {
  1154.   int count, where;
  1155.   int part = 0;
  1156.   FILE *uu; /* pipe */
  1157.  
  1158.   /* check if every part is in */
  1159.   for (count =1; count < reg.Parts + 1; count ++)
  1160.     {
  1161.       if (whereispart(count, reg) == 0)
  1162.     {
  1163.       printf("Part %d not found, decoding of file %s aborted\n",
  1164.           count, reg.Filename);
  1165.       return(0);
  1166.     }
  1167.     }
  1168.   fflush(stdout);
  1169.   if ( (uu=popen("uudecode","w") ) == NULL)
  1170.     perror("unable to pipe open uudecode");
  1171.   for (count =1 ;count <reg.Parts+1; count++)
  1172.     {
  1173.       where=whereispart(count,reg);
  1174.       DownLoad(Filereg[where].Article,uu);
  1175.       Filereg[where].Filename[0] = '\0'; /* mark it USED */
  1176.     }
  1177.   pclose(uu);
  1178.   return(1);  /* success */
  1179. } /* end of MakeOnePicture */
  1180.  
  1181. /***************************************/
  1182. int whereispart(partno, reg)
  1183. int partno;
  1184. struct superblock reg;
  1185. {
  1186.   int count;
  1187.  
  1188.   for (count =1; count <filecount +1; count++)
  1189.     if ( (Filereg[count].Part == partno)
  1190.     && (strcmp(Filereg[count].Filename, reg.Filename) == 0))
  1191.       return(count);
  1192.  
  1193.   /* part not found: mark them USED */
  1194.   for (count=1; count <filecount +1; count++)
  1195.     if ( strcmp(Filereg[count].Filename, reg.Filename) == 0)
  1196.       Filereg[count].Filename[0] = '\0';
  1197.   return(0);
  1198. } /* end of whereispart() */
  1199.  
  1200.  
  1201. /***************************************/
  1202. DownLoad(article,to)
  1203. int article;
  1204. FILE *to;
  1205. {
  1206.   char buf[LEN], a[LEN], b[LEN];
  1207.   int ret,len;
  1208.  
  1209.   sprintf(line,"body %d", article);
  1210.   put_server(line);
  1211.  
  1212.   /* find the start point */
  1213.   while ( (ret=get_server(buf,LEN)) != -1)
  1214.     {
  1215.       if (strcmp(buf,".") == 0)
  1216.     return(1); /* reach file end without any meaningful contents */
  1217.       if ( ( (strncmp(buf, "begin ", 6) == 0) && (isdigit(buf[6])) ) 
  1218.       ||
  1219.        ( (buf[0]=='M') && (strlen(buf) >59) && (strlen(buf) <71) ) )
  1220.     {
  1221.       a[0]=b[0]='\0';
  1222.       fprintf(to,"%s\n",buf);
  1223.       break; /* real stuff begins */
  1224.     }
  1225.     }
  1226.   if (ret==-1)
  1227.       perror("cannot get_server at body command");
  1228.  
  1229.   /* pipe everthing to uudecode */
  1230.   while ( (ret=get_server(buf,LEN)) != -1)
  1231.     {
  1232.       if (strcmp(buf,".")==0)
  1233.     break;
  1234.       if (strncmp(buf, "end", 3) == 0)
  1235.     {
  1236.       if (b[0])
  1237.         fprintf(to,"%s\n",b);
  1238.       if (a[0])
  1239.         fprintf(to,"%s\n",a);
  1240.       fprintf(to,"%s\n",buf);
  1241.     }
  1242. /*      else if (strncmp(buf,"END", 3) == 0)
  1243.     break;
  1244. */
  1245.       else
  1246.     {
  1247.       len=strlen(buf);
  1248.       if ( (buf[0] != 'M' || len <60 || len >70 )
  1249.           && (strncmp(buf,"begin ", 5)) )
  1250.         {
  1251.           strcpy(b,a);
  1252.           strcpy(a,buf);
  1253.           continue;
  1254.         }
  1255.       a[0]=b[0]='\0';
  1256.       fprintf(to,"%s\n",buf);
  1257.     }
  1258.     } /* end of 2nd while */
  1259.   if (ret==-1)
  1260.     perror("get_server err 2nd at body command");
  1261.     
  1262. }
  1263.  
  1264. /***************************************/
  1265. struct superblock 
  1266. nextfilereg()
  1267. {
  1268.   int count;
  1269.   static struct superblock nulblock =
  1270.     { "\0", 0, 0, 0 };
  1271.  
  1272.   for (count=1; count<filecount +1; count++) /*filecount start at 1 */
  1273.     if ( Filereg[count].Filename[0] != '\0') /* USED? */
  1274.       return(Filereg[count]);
  1275.   return(nulblock);
  1276. } /* end of nextfilereg() */
  1277.  
  1278. /***********************************************************/
  1279. /* Read a subject line, getinfo, and store into superblock */
  1280. SubjectAnalysis()
  1281. {
  1282. char trash[LEN];
  1283. char start[LEN], end[LEN];
  1284. int  ret;
  1285.  
  1286. /* borrowed from update.c */
  1287.  
  1288. sprintf(line, "group %s\n", newsgroup);
  1289. put_server(line);
  1290.  
  1291. ret=get_server(buf, LEN);
  1292. if (ret == -1)
  1293.   perror("cannot get_server after group command");
  1294. else if ( strncmp(buf, "411", 3) == 0 ) 
  1295.   {
  1296.     fprintf(stderr,"no such group as %s\n", newsgroup);
  1297.     exit(0);
  1298.   }
  1299.  
  1300. sscanf(buf,"%s%s%s%s", trash,trash, start, end);
  1301.  
  1302. printf("The available articles are Numbered %s to %s\n", start, end);
  1303. #ifndef DEBUG
  1304. puts("Gathering info ...");
  1305. #endif
  1306.  
  1307. if (index_start == 0)
  1308.   {
  1309.     index_start = atoi(start);
  1310.     index_end   = atoi(end);
  1311.   }
  1312. sprintf(line, "xhdr subject %d-%d\n",index_start, index_end );
  1313.  
  1314. put_server(line);
  1315.  
  1316. while ( (ret=get_server(buf,LEN)) != -1 )
  1317.   {
  1318.     if ( strcmp(buf,".") == 0 )
  1319.       break;
  1320.     getinfo(buf);    
  1321.   }
  1322.  
  1323. if (ret==-1)
  1324.   perror("get_server error in xhdr");
  1325.  
  1326. } /* end of SubjectAnalysis */
  1327.  
  1328. /***************************************************************/
  1329. /* get filename, part info, article number from subject line   */
  1330. /* store into Filereg[filecount++]                             */
  1331. #include <ctype.h>
  1332.  
  1333. char word[LEN],oldword[LEN];
  1334.  
  1335. getinfo(buf)
  1336. char *buf;
  1337. {
  1338. int t1,t2;
  1339.  
  1340. filecount++;
  1341.  
  1342. #ifdef DEBUG
  1343.     puts(buf);
  1344. #endif
  1345.     if (GetArticleNumber(buf) == 0)
  1346.       fprintf(stderr,"get article number error: buf=%s",buf);
  1347.  
  1348.     if ( isRE(buf) )
  1349.       {
  1350. #ifdef DEBUG
  1351.     puts("Regarding ... -- TRASH");
  1352. #endif
  1353.     filecount--; /* don't want this into Filereg */
  1354.     return;
  1355.       }
  1356.     t1=GetSubject(buf);
  1357.     t2=GetPartInfo(buf);
  1358.     
  1359.     if ( t1 && (Filereg[filecount].Part != 0)
  1360.         && (Filereg[filecount].Parts != 0) )
  1361.       ;
  1362.     else if ( (!t1) && (Filereg[filecount].Part !=0 )
  1363.                 && (Filereg[filecount].Parts != 0) )
  1364.       strcpy(Filereg[filecount].Filename,  getword(buf));
  1365.     else if ( t1 && ( !t2 ) ) /* for careless poster */
  1366.       Filereg[filecount].Part= Filereg[filecount].Parts= 1;
  1367.     else       
  1368.       {
  1369. #ifdef DEBUG
  1370.     puts("part 0, or text file -- TRASH");
  1371. #endif
  1372.     filecount--; /* don't want this into Filereg */
  1373.     return;
  1374.       }
  1375. #ifdef DEBUG
  1376.     printf("\tarticle=%d, filename=%s, part= %d, parts=%d\n",
  1377.        Filereg[filecount].Article, Filereg[filecount].Filename,
  1378.        Filereg[filecount].Part, Filereg[filecount].Parts);
  1379. #endif
  1380. }
  1381.  
  1382. /******************************************/
  1383. GetArticleNumber(buf)
  1384. char *buf;
  1385. {
  1386. char tmp[LEN];
  1387.  
  1388. strcpy(tmp,getword(buf));
  1389. if (!isnumber(tmp))
  1390.   return(0);
  1391. else
  1392.   {
  1393.     Filereg[filecount].Article=atoi(tmp);
  1394.     return(1);
  1395.   }
  1396. }
  1397.  
  1398. /******************************************/
  1399. GetSubject(buf)
  1400. char *buf;
  1401. {
  1402. char line[LEN];
  1403.  
  1404. strcpy(line,buf); /* don't wanna destroy buf */
  1405.  
  1406. do
  1407.   {
  1408.     strcpy(word,getword(line));
  1409.     if ( (word[0] == '.')
  1410.     && isstring(oldword)
  1411.     && isstring(peekword(line))  )
  1412.       {
  1413.     sprintf(Filereg[filecount].Filename,"%s.%s",oldword,getword(line));
  1414.     return(1);
  1415.       }
  1416.     strcpy(oldword,word);
  1417.   }while (word[0]!='\0');
  1418.  
  1419. return(0);
  1420. }
  1421.  
  1422. /**********************************************/
  1423. GetPartInfo(buf)
  1424. char *buf;
  1425. {
  1426. char line[LEN];
  1427.  
  1428. strcpy(line,buf);
  1429. do
  1430.   {
  1431.     strcpy(word,getword(line));
  1432.     if ( ( (word[0] == '/') || (strcmp(word,"of") == 0))
  1433.     && isnumber(oldword)
  1434.     && isnumber(peekword(line))   )
  1435.       {
  1436.       Filereg[filecount].Part=atoi(oldword);
  1437.       Filereg[filecount].Parts=atoi(getword(line));
  1438.       return(1);
  1439.     }
  1440.     strcpy(oldword,word);
  1441.   }while (word[0]!='\0');
  1442. return(0);
  1443. }    
  1444.  
  1445. /*****************************************/ 
  1446. getword(line)
  1447. char *line;
  1448. {
  1449. int i;
  1450. char backup[LEN];
  1451. char tmp;
  1452.  
  1453. if (line[0] == '\0') 
  1454.      /* is it empty? -- different machines treat isspace differently */
  1455.   return("\0");
  1456. strcpy(backup,line);
  1457.  
  1458. if (isspace(backup[0]))   /* space? ignor */
  1459.   strcpy(backup,line+1);
  1460. if (backup[0] == '\0')  /* is it empty ? */
  1461.   return("\0");
  1462. if (!isalnum(backup[0]))  /* begin with non alnum? return it */
  1463.     {
  1464.       strcpy(line,backup+1);
  1465.       backup[1]='\0';
  1466.       return(backup);
  1467.     }
  1468.  
  1469. for (i=0; backup[i] != '\0'; i++)
  1470.   {
  1471.   if  (!isalnum(backup[i]))
  1472.     {
  1473.       strcpy(line,backup+i);
  1474.       backup[i]='\0';
  1475.       return(backup);
  1476.     }
  1477.   else if (isupper(backup[i]))
  1478.     {
  1479.       tmp=tolower(backup[i]);
  1480.       backup[i]=tmp;
  1481.     }
  1482.  }
  1483. line[0]='\0';
  1484. return (backup);
  1485. }
  1486.  
  1487. /***********************************************/
  1488. peekword(line)
  1489. char *line;
  1490. {
  1491. int i;
  1492. char backup[LEN];
  1493. char tmp;
  1494.  
  1495. if (line[0] == '\0')
  1496.   return("\0");
  1497. strcpy(backup,line);
  1498.  
  1499. if (isspace(backup[0]))   /* space? ignore */
  1500.   strcpy(backup,line+1);
  1501. if (backup[0] == '\0')
  1502.   return("\0");
  1503. if (!isalnum(backup[0]))
  1504.   {
  1505.     backup[i]='\0';
  1506.     return(backup);
  1507.   }
  1508. for (i=0; backup[i]!='\0' ;i++)
  1509.   if (!isalnum(backup[i]))
  1510.       {
  1511.     backup[i]='\0';
  1512.     return(backup);
  1513.       }
  1514.   else if (isupper(backup[i]))
  1515.     {
  1516.       tmp=tolower(backup[i]);
  1517.       backup[i]=tmp;
  1518.     }
  1519. return(backup);
  1520. }
  1521.  
  1522. /**************************************************/
  1523. int isstring(string)
  1524. char *string;
  1525. {
  1526. int i;
  1527.  
  1528. for (i=0;i<strlen(string);i++)
  1529.   if (!isalnum(string[i]))
  1530.     return(0);
  1531. return(1);
  1532. }
  1533.  
  1534. /*************************************************/
  1535. int isnumber(string)
  1536. char *string;
  1537. {
  1538. int i;
  1539.  
  1540. for (i=0;i<strlen(string); i++)
  1541.   if (!isdigit(string[i]))
  1542.     return(0);
  1543. return(1);
  1544. }
  1545.  
  1546. /*************************************************/
  1547. isRE(buf)
  1548. char *buf;
  1549. {
  1550. char line[LEN];
  1551. char word[LEN];
  1552.  
  1553. strcpy(line,buf);
  1554. do
  1555.   {
  1556.     strcpy(word, getword(line));
  1557.   }
  1558. while (!isstring(word)); /* find first string */
  1559.  
  1560. return(!strcmp(word,"re"));
  1561. }
  1562. /*********************** END **********************/
  1563. SHAR_EOF
  1564. fi # end of overwriting check
  1565. #    End of shell archive
  1566. exit 0
  1567.