[ Article crossposted from alt.binaries.pictures.utilities ] [ Author was Jonathan Wang ] [ Posted on Mon, 14 Jun 1993 15:45:26 GMT ] Some of my friends urged me to post this util for public use so that our netters can use their time more productively, instead of wasting it by doing those time consuming downloads and reassembling of files from USENET. wang.c V4.0 is planned to be a friendly USENET download-and-assemble utility, aimed at grabbing picture & audio files, zipped packages, and any other uuencoded binary posts. Instead of: 1)saving the articles from the newsreader, 2)getting rid of the news header and other trash, 3)concatenating them into proper order, and 4)piping it to uudecode, now all you have to do is to type "wang". Use "wang -h" for further help. Some old USENET folks may still remember the previous wang.c versions that appeared last year. Thanks to hundreds of loyal wang.c users, I, as a unix C newcomer, have the courage to keep updating this util to a new version. The new version has a greatly enhanced ability to "understand" the subject line, and most important of all, the ability to access USENET directly without any newsreader. wang.c is by no means meant to challenge the masterpiece pearl script of aub, and the other existing decoders. The objective is only to facilitate the lazy netters like myself who are satisfied at getting the job done, instead of getting it done perfectly. After downloading this package, you can simply type in "make wang", and then, type "wang". Boom! it goes. Important Notice: By default, wang will download EVERYTHING from one newsgroup at a time if you don't specify a range. Take the group alt.binaries.pictures.misc for example: it will take about half an hour to download some 150 pictures. That means there exists the potential for filling up your disk and slowing down your system. Please avoid using "nohup wang &" and log off. KEEP your eyes on this monster! I advise my dear users to consult the sysadms before using it. I still haven't tested it thoroughly. All I can tell now is that it will run on sysv, bsd and sunos. If you can get it compiled on any other platforms, please let me know. Yes, theoretically, it will run on any unix box which supports TCP/IP. No, it won't compile on a PC. My sincere acknowledgement and admiration goes to Iain Lea, the author of the famous tin newreader. All my networking code has been stolen from this genius mind and subsequently adapted to solve this problem. No Copyright is hereby claimed. Sell it if you can. But I do appreciate if you will mention my name. Jonathan Wang, June, 1933. #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # README # nntplib.c # nntplib.h # nntpservers # wang.c # This archive created: Mon Jun 14 11:42:28 1993 export PATH; PATH=/bin:$PATH if test -f 'README' then echo shar: will not over-write existing file "'README'" else cat << \SHAR_EOF > 'README' Some of my friends urged me to post this util for public use so that our netters can use their time more productively, instead of wasting it by doing those time consuming downloads and reassembling of files from USENET. wang.c V4.0 is planned to be a friendly USENET download-and-assemble utility, aimed at grabbing picture & audio files, zipped packages, and any other uuencoded binary posts. Instead of: 1)saving the articles from the newsreader, 2)getting rid of the news header and other trash, 3)concatenating them into proper order, and 4)piping it to uudecode, now all you have to do is to type "wang". Use "wang -h" for further help. Some old USENET folks may still remember the previous wang.c versions that appeared last year. Thanks to hundreds of loyal wang.c users, I, as a unix C newcomer, have the courage to keep updating this util to a new version. The new version has a greatly enhanced ability to "understand" the subject line, and most important of all, the ability to access USENET directly without any newsreader. wang.c is by no means meant to challenge the masterpiece pearl script of aub, and the other existing decoders. The objective is only to facilitate the lazy netters like myself who are satisfied at getting the job done, instead of getting it done perfectly. After downloading this package, you can simply type in "make wang", and then, type "wang". Boom! it goes. Important Notice: By default, wang will download EVERYTHING from one newsgroup at a time if you don't specify a range. Take the group alt.binaries.pictures.misc for example: it will take about half an hour to download some 150 pictures. That means there exists the potential for filling up your disk and slowing down your system. Please avoid using "nohup wang &" and log off. KEEP your eyes on this monster! I advise my dear users to consult the sysadms before using it. I still haven't tested it thoroughly. All I can tell now is that it will run on sysv, bsd and sunos. If you can get it compiled on any other platforms, please let me know. Yes, theoretically, it will run on any unix box which supports TCP/IP. No, it won't compile on a PC. My sincere acknowledgement and admiration goes to Iain Lea, the author of the famous tin newreader. All my networking code has been stolen from this genius mind and subsequently adapted to solve this problem. No Copyright is hereby claimed. Sell it if you can. But I do appreciate if you will mention my name. Jonathan Wang, June, 1933. SHAR_EOF fi # end of overwriting check if test -f 'nntplib.c' then echo shar: will not over-write existing file "'nntplib.c'" else cat << \SHAR_EOF > 'nntplib.c' /* * Project : tin - a threaded Netnews reader * Module : nntplib.c * Author : S.Barber & I.Lea * Created : 12-01-91 * Updated : 07-11-92 * Notes : NNTP client routines taken from clientlib.c 1.5.11 (10-02-91) * Copyright : (c) Copyright 1991-93 by Stan Barber & Iain Lea * Permission is hereby granted to copy, reproduce, redistribute * or otherwise use this software as long as: there is no * monetary profit gained specifically from the use or * reproduction or this software, it is not sold, rented, * traded or otherwise marketed, and this copyright notice * is included prominently in any copy made. */ /**************************/ #define NNTP_ABLE 1 #define NNTP_ONLY 1 #include #include #include #include #include "nntplib.h" /**************************/ /* #include "tin.h" */ #ifdef NNTP_ONLY # ifndef NNTP_ABLE # define NNTP_ABLE # endif #endif #ifndef CDROM_ABLE FILE *nntp_rd_fp = NULL; FILE *nntp_wr_fp = NULL; extern int errno; #ifdef NNTP_ABLE # ifdef TLI # include # include # include # include # ifdef WIN_TCP # include # else # include # endif # define IPPORT_NNTP ((unsigned short) 119) # include /* All TLI implementations may not have this */ # else # ifdef apollo # include # include # include # else # include # include # ifndef EXCELAN # include # endif # endif # endif /* !TLI */ # ifndef BSD # define index(a,b) strchr(a,b) # define bcopy(a,b,c) memcpy(b,a,c) # define bzero(a,b) memset(a,'\0',b) # endif # ifdef EXCELAN # if __STDC__ int connect (int, struct sockaddr *); unsigned short htons (unsigned short); unsigned long rhost (char **); int rresvport (int); int socket (int, struct sockproto *, struct sockaddr_in *, int); # endif # endif # ifdef DECNET # include # include # endif #endif /* NNTP_ABLE */ /* * getserverbyfile Get the name of a server from a named file. * Handle white space and comments. * Use NNTPSERVER environment variable if set. * * Parameters: "file" is the name of the file to read. * * Returns: Pointer to static data area containing the * first non-ws/comment line in the file. * NULL on error (or lack of entry in file). * * Side effects: None. */ char *getserverbyfile (file) char *file; { #ifdef NNTP_ABLE register FILE *fp; register char *cp; static char buf[256]; if (cp = (char *) getenv ("NNTPSERVER")) { (void) strcpy (buf, cp); return (buf); } if (file == NULL) return (NULL); if ((fp = fopen (file, "r")) == NULL) return (NULL); while (fgets (buf, sizeof (buf), fp) != NULL) { if (*buf == '\n' || *buf == '#') { continue; } cp = (char *) index(buf, '\n'); if (cp) { *cp = '\0'; } (void) fclose (fp); return (buf); } (void) fclose (fp); #endif /* NNTP_ABLE */ return (NULL); /* No entry */ } /* * server_init Get a connection to the remote server. * * Parameters: "machine" is the machine to connect to. * "service" is the service to connect to on the machine. * "port" is the servive port to connect to. * * Returns: -1 on error * server's initial response code on success. * * Side effects: Connects to server. * "nntp_rd_fp" and "nntp_wr_fp" are fp's * for reading and writing to server. */ int server_init (machine, service, port) char *machine; char *service; unsigned short port; { #ifdef NNTP_ABLE int sockt_rd, sockt_wr; char line[256]; #ifdef DECNET char *cp; cp = (char *) index(machine, ':'); if (cp && cp[1] == ':') { *cp = '\0'; sockt_rd = get_dnet_socket (machine, service); } else { sockt_rd = get_tcp_socket (machine, service, port); } #else sockt_rd = get_tcp_socket (machine, service, port); #endif if (sockt_rd < 0) return (-1); /* * Now we'll make file pointers (i.e., buffered I/O) out of * the socket file descriptor. Note that we can't just * open a fp for reading and writing -- we have to open * up two separate fp's, one for reading, one for writing. */ if ((nntp_rd_fp = (FILE *) fdopen (sockt_rd, "r")) == NULL) { perror ("server_init: fdopen #1"); return (-1); } sockt_wr = dup (sockt_rd); #ifdef TLI if (t_sync (sockt_rd) < 0) { /* Sync up new fd with TLI */ t_error ("server_init: t_sync"); nntp_rd_fp = NULL; /* from above */ return (-1); } #endif if ((nntp_wr_fp = (FILE *) fdopen (sockt_wr, "w")) == NULL) { perror ("server_init: fdopen #2"); nntp_rd_fp = NULL; /* from above */ return (-1); } /* * Now get the server's signon message */ (void) get_server (line, sizeof (line)); return (atoi (line)); #else return (-1); #endif /* NNTP_ABLE */ } /* * get_tcp_socket -- get us a socket connected to the specified server. * * Parameters: "machine" is the machine the server is running on. * "service" is the service to connect to on the server. * "port" is the port to connect to on the server. * * Returns: Socket connected to the server if * all is ok, else -1 on error. * * Side effects: Connects to server. * * Errors: Printed via perror. */ int get_tcp_socket (machine, service, port) char *machine; /* remote host */ char *service; /* nttp/smtp etc. */ unsigned short port; /* tcp port number */ { #ifdef NNTP_ABLE int s = -1; struct sockaddr_in sin; #ifdef TLI struct hostent *gethostbyname (), *hp; struct t_call *callptr; /* * Create a TCP transport endpoint. */ if ((s = t_open ("/dev/tcp", O_RDWR, (struct t_info*) 0)) < 0){ t_error ("t_open: can't t_open /dev/tcp"); return (-1); } if (t_bind (s, (struct t_bind *) 0, (struct t_bind *) 0) < 0) { t_error ("t_bind"); t_close (s); return (-1); } bzero((char *) &sin, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_port = htons (port); if (!isdigit(*machine) || (long)(sin.sin_addr.s_addr = inet_addr (machine)) == -1) { if((hp = gethostbyname (machine)) == NULL) { fprintf (stderr, "gethostbyname: %s: host unknown\n", machine); t_close (s); return (-1); } bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length); } /* * Allocate a t_call structure and initialize it. * Let t_alloc() initialize the addr structure of the t_call structure. */ if ((callptr = (struct t_call *) t_alloc (s,T_CALL,T_ADDR)) == NULL){ t_error ("t_alloc"); t_close (s); return (-1); } callptr->addr.maxlen = sizeof (sin); callptr->addr.len = sizeof (sin); callptr->addr.buf = (char *) &sin; callptr->opt.len = 0; /* no options */ callptr->udata.len = 0; /* no user data with connect */ /* * Connect to the server. */ if (t_connect (s, callptr, (struct t_call *) 0) < 0) { t_error ("t_connect"); t_close (s); return (-1); } /* * Now replace the timod module with the tirdwr module so that * standard read() and write() system calls can be used on the * descriptor. */ if (ioctl (s, I_POP, (char *) 0) < 0) { perror ("I_POP(timod)"); t_close (s); return (-1); } if (ioctl (s, I_PUSH, "tirdwr") < 0) { perror ("I_PUSH(tirdwr)"); t_close (s); return (-1); } #else /* !TLI */ #ifndef EXCELAN struct servent *getservbyname(), *sp; struct hostent *gethostbyname(), *hp; #ifdef h_addr int x = 0; register char **cp; static char *alist[1]; #endif /* h_addr */ unsigned long inet_addr(); static struct hostent def; static struct in_addr defaddr; static char namebuf[256]; if ((sp = getservbyname (service, "tcp")) == NULL) { fprintf (stderr, "%s/tcp: Unknown service.\n", service); return (-1); } /* If not a raw ip address, try nameserver */ if (!isdigit(*machine) || (long)(defaddr.s_addr = inet_addr (machine)) == -1) hp = gethostbyname (machine); else { /* Raw ip address, fake */ (void) strcpy (namebuf, machine); def.h_name = namebuf; #ifdef h_addr def.h_addr_list = alist; #endif def.h_addr = (char *) &defaddr; def.h_length = sizeof (struct in_addr); def.h_addrtype = AF_INET; def.h_aliases = 0; hp = &def; } if (hp == NULL) { fprintf (stderr, "\n%s: Unknown host.\n", machine); return (-1); } bzero((char *) &sin, sizeof (sin)); sin.sin_family = hp->h_addrtype; sin.sin_port = sp->s_port; #else /* EXCELAN */ bzero((char *) &sin, sizeof (sin)); sin.sin_family = AF_INET; #endif /* EXCELAN */ /* * The following is kinda gross. The name server under 4.3 * returns a list of addresses, each of which should be tried * in turn if the previous one fails. However, 4.2 hostent * structure doesn't have this list of addresses. * Under 4.3, h_addr is a #define to h_addr_list[0]. * We use this to figure out whether to include the NS specific * code... */ #ifdef h_addr /* * get a socket and initiate connection -- use multiple addresses */ for (cp = hp->h_addr_list; cp && *cp; cp++) { s = socket (hp->h_addrtype, SOCK_STREAM, 0); if (s < 0) { perror ("socket"); return (-1); } bcopy(*cp, (char *) &sin.sin_addr, hp->h_length); if (x < 0) { fprintf (stderr, "Trying %s", (char *) inet_ntoa (sin.sin_addr)); } x = connect (s, (struct sockaddr *) &sin, sizeof (sin)); if (x == 0) { break; } fprintf (stderr, "\nConnection to %s: ", (char *) inet_ntoa (sin.sin_addr)); perror (""); (void) close (s); } if (x < 0) { fprintf (stderr, "Giving up...\n"); return (-1); } #else /* no name server */ #ifdef EXCELAN if ((s = socket (SOCK_STREAM,(struct sockproto *)NULL,&sin,SO_KEEPALIVE)) < 0) { /* Get the socket */ perror ("socket"); return (-1); } bzero((char *) &sin, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_port = htons (IPPORT_NNTP); /* set up addr for the connect */ if ((sin.sin_addr.s_addr = rhost (&machine)) == -1) { fprintf (stderr, "\n%s: Unknown host.\n", machine); return (-1); } /* And then connect */ if (connect (s, (struct sockaddr *)&sin) < 0) { perror ("connect"); (void) close (s); return (-1); } #else /* not EXCELAN */ if ((s = socket (AF_INET, SOCK_STREAM, 0)) < 0) { perror ("socket"); return (-1); } /* And then connect */ bcopy (hp->h_addr, (char *) &sin.sin_addr, hp->h_length); if (connect (s, (struct sockaddr *) &sin, sizeof (sin)) < 0) { perror ("connect"); (void) close (s); return (-1); } #endif /* !EXCELAN */ #endif /* !h_addr */ #endif /* !TLI */ return (s); #else return (-1); #endif /* NNTP_ABLE */ } #ifdef DECNET /* * get_dnet_socket -- get us a socket connected to the server. * * Parameters: "machine" is the machine the server is running on. * "service" is the name of the service to connect to. * * Returns: Socket connected to the news server if * all is ok, else -1 on error. * * Side effects: Connects to server. * * Errors: Printed via nerror. */ int get_dnet_socket (machine, service) char *machine; char *service; { #ifdef NNTP_ABLE int s, area, node; struct sockaddr_dn sdn; struct nodeent *getnodebyname(), *np; bzero((char *) &sdn, sizeof (sdn)); switch (s = sscanf (machine, "%d%*[.]%d", &area, &node)) { case 1: node = area; area = 0; case 2: node += area*1024; sdn.sdn_add.a_len = 2; sdn.sdn_family = AF_DECnet; sdn.sdn_add.a_addr[0] = node % 256; sdn.sdn_add.a_addr[1] = node / 256; break; default: if ((np = getnodebyname (machine)) == NULL) { fprintf (stderr, "%s: Unknown host.\n", machine); return (-1); } else { bcopy(np->n_addr, (char *) sdn.sdn_add.a_addr, np->n_length); sdn.sdn_add.a_len = np->n_length; sdn.sdn_family = np->n_addrtype; } break; } sdn.sdn_objnum = 0; sdn.sdn_flags = 0; sdn.sdn_objnamel = strlen ("NNTP"); bcopy("NNTP", &sdn.sdn_objname[0], sdn.sdn_objnamel); if ((s = socket (AF_DECnet, SOCK_STREAM, 0)) < 0) { nerror ("socket"); return (-1); } /* And then connect */ if (connect (s, (struct sockaddr *) &sdn, sizeof (sdn)) < 0) { nerror ("connect"); close (s); return (-1); } return (s); #else return (-1); #endif /* NNTP_ABLE */ } #endif /* * handle_server_response * * Print some informative messages based on the server's initial * response code. This is here so inews, rn, etc. can share * the code. * * Parameters: "response" is the response code which the * server sent us, presumably from "server_init", * above. * "nntpserver" is the news server we got the * response code from. * * Returns: -1 if the error is fatal (and we should exit). * 0 otherwise. * * Side effects: None. */ int handle_server_response (response, nntpserver) int response; char *nntpserver; { #ifdef NNTP_ABLE switch (response) { case OK_NOPOST: /* fall through */ printf ("NOTE: This machine does not have permission to post articles.\n"); printf (" Please don't waste your time trying.\n\n"); case OK_CANPOST: return (0); break; case ERR_ACCESS: printf ("This machine does not have permission to use the %s news server.\n", nntpserver); return (-1); break; default: printf ("Unexpected response code from %s news server: %d\n", nntpserver, response); return (-1); break; } /*NOTREACHED*/ #else return (-1); #endif /* NNTP_ABLE */ } /* * put_server -- send a line of text to the server, terminating it * with CR and LF, as per ARPA standard. * * Parameters: "string" is the string to be sent to the * server. * * Returns: Nothing. * * Side effects: Talks to the server. * * Note: This routine flushes the buffer each time * it is called. For large transmissions * (i.e., posting news) don't use it. Instead, * do the fprintf's yourself, and then a final * fflush. */ void put_server (string) char *string; { #ifdef NNTP_ABLE fprintf (nntp_wr_fp, "%s\r\n", string); (void) fflush (nntp_wr_fp); #endif /* NNTP_ABLE */ } /* * get_server -- get a line of text from the server. Strips * CR's and LF's. * * Parameters: "string" has the buffer space for the * line received. * "size" is the size of the buffer. * * Returns: -1 on error, 0 otherwise. * * Side effects: Talks to server, changes contents of "string". */ int get_server (string, size) char *string; int size; { #ifdef NNTP_ABLE register char *cp; while (fgets (string, size, nntp_rd_fp) == NULL) { if (errno != EINTR) { return (-1); } } if ((cp = (char *) index(string, '\r')) != NULL) { *cp = '\0'; } else if ((cp = (char *) index(string, '\n')) != NULL) { *cp = '\0'; } return (0); #else return (-1); #endif /* NNTP_ABLE */ } /* * close_server -- close the connection to the server, after sending * the "quit" command. * * Parameters: None. * * Returns: Nothing. * * Side effects: Closes the connection with the server. * You can't use "put_server" or "get_server" * after this routine is called. */ void close_server () { #ifdef NNTP_ABLE char ser_line[256]; if (nntp_wr_fp == NULL || nntp_rd_fp == NULL) return; put_server ("QUIT"); (void) get_server (ser_line, sizeof (ser_line)); (void) fclose (nntp_wr_fp); (void) fclose (nntp_rd_fp); #endif /* NNTP_ABLE */ } #endif /* CDROM_ABLE */ SHAR_EOF fi # end of overwriting check if test -f 'nntplib.h' then echo shar: will not over-write existing file "'nntplib.h'" else cat << \SHAR_EOF > 'nntplib.h' /* * Project : tin - a threaded Netnews reader * Module : nntplib.h * Author : I.Lea * Created : 01-04-91 * Updated : 18-11-92 * Notes : nntp.h 1.5.11/1.6 with extensions for tin & CD-ROM * Copyright : You may freely copy or redistribute this software, * so long as there is no profit made from its use, sale * trade or reproduction. You may not change this copy- * right notice, and it must be included in any copy made */ #ifndef NNTP_SERVER_FILE # define NNTP_SERVER_FILE "/etc/nntpserver" #endif #define NNTP_TCP_NAME "nntp" #define NNTP_TCP_PORT ((unsigned short) 119) #ifndef SMTP_SERVER_FILE # define SMTP_SERVER_FILE "/etc/smtpserver" #endif #define SMTP_TCP_NAME "smtp" #define SMTP_TCP_PORT ((unsigned short) 25) /* * External routine declarations */ extern char *getserverbyfile(); /* extern int server_init(); */ extern int get_tcp_socket(); extern int handle_server_response(); extern void put_server(); extern int get_server(); extern void close_server(); /* * External file descriptors for the server connection */ extern FILE *nntp_wr_fp; /* * Response codes for NNTP server * * @(#)Header: nntp.h,v 1.81 92/03/12 02:08:31 sob Exp $ * * First digit: * * 1xx Informative message * 2xx Command ok * 3xx Command ok so far, continue * 4xx Command was correct, but couldn't be performed * for some specified reason. * 5xx Command unimplemented, incorrect, or a * program error has occured. * * Second digit: * * x0x Connection, setup, miscellaneous * x1x Newsgroup selection * x2x Article selection * x3x Distribution * x4x Posting */ #define CHAR_INF '1' #define CHAR_OK '2' #define CHAR_CONT '3' #define CHAR_ERR '4' #define CHAR_FATAL '5' #define INF_HELP 100 /* Help text on way */ #define INF_AUTH 180 /* Authorization capabilities */ #define INF_DEBUG 199 /* Debug output */ #define OK_CANPOST 200 /* Hello; you can post */ #define OK_NOPOST 201 /* Hello; you can't post */ #define OK_SLAVE 202 /* Slave status noted */ #define OK_GOODBYE 205 /* Closing connection */ #define OK_GROUP 211 /* Group selected */ #define OK_GROUPS 215 /* Newsgroups follow */ #define OK_XMOTD 217 /* News motd follows */ #define OK_XINDEX 218 /* Tin style index follows */ #define OK_XOVERVIEW 219 /* .overview style index follows */ #define OK_ARTICLE 220 /* Article (head & body) follows */ #define OK_HEAD 221 /* Head follows */ #define OK_BODY 222 /* Body follows */ #define OK_NOTEXT 223 /* No text sent -- stat, next, last */ #define OK_NEWNEWS 230 /* New articles by message-id follow */ #define OK_NEWGROUPS 231 /* New newsgroups follow */ #define OK_XFERED 235 /* Article transferred successfully */ #define OK_POSTED 240 /* Article posted successfully */ #define OK_AUTHSYS 280 /* Authorization system ok */ #define OK_AUTH 281 /* Authorization (user/pass) ok */ #define OK_BIN 282 /* binary data follows */ #define OK_SPLIST 283 /* spooldir list follows */ #define OK_SPSWITCH 284 /* Switching to a different spooldir */ #define OK_SPNOCHANGE 285 /* Still using same spooldir */ #define OK_SPLDIRCUR 286 /* Current spooldir */ #define OK_SPLDIRAVL 287 /* Available spooldir */ #define OK_SPLDIRERR 288 /* Unavailable spooldir or invalid entry */ #define CONT_XFER 335 /* Continue to send article */ #define CONT_POST 340 /* Continue to post article */ #define NEED_AUTHINFO 380 /* authorization is required */ #define NEED_AUTHDATA 381 /* authorization data required */ #define ERR_GOODBYE 400 /* Have to hang up for some reason */ #define ERR_NOGROUP 411 /* No such newsgroup */ #define ERR_NCING 412 /* Not currently in newsgroup */ #define ERR_XMOTD 417 /* No news motd file */ #define ERR_XINDEX 418 /* No tin index for this group */ #define ERR_XOVERVIEW 419 /* No .overview index for this group */ #define ERR_NOCRNT 420 /* No current article selected */ #define ERR_NONEXT 421 /* No next article in this group */ #define ERR_NOPREV 422 /* No previous article in this group */ #define ERR_NOARTIG 423 /* No such article in this group */ #define ERR_NOART 430 /* No such article at all */ #define ERR_GOTIT 435 /* Already got that article, don't send */ #define ERR_XFERFAIL 436 /* Transfer failed */ #define ERR_XFERRJCT 437 /* Article rejected, don't resend */ #define ERR_NOPOST 440 /* Posting not allowed */ #define ERR_POSTFAIL 441 /* Posting failed */ #define ERR_NOAUTH 480 /* authorization required for command */ #define ERR_AUTHSYS 481 /* Authorization system invalid */ #define ERR_AUTHREJ 482 /* Authorization data rejected */ #define ERR_INVALIAS 483 /* Invalid alias on spooldir cmd */ #define ERR_INVNOSPDIR 484 /* No spooldir file found */ #define ERR_COMMAND 500 /* Command not recognized */ #define ERR_CMDSYN 501 /* Command syntax error */ #define ERR_ACCESS 502 /* Access to server denied */ #define ERR_FAULT 503 /* Program fault, command not performed */ #define ERR_AUTHBAD 580 /* Authorization Failed */ /* * RFC 977 defines this; don't change it. */ #define NNTP_STRLEN 512 SHAR_EOF fi # end of overwriting check if test -f 'nntpservers' then echo shar: will not over-write existing file "'nntpservers'" else cat << \SHAR_EOF > 'nntpservers' /**********************************************************/ /* This is a short list of public accessable NNTP servers */ /* by Jonathan Wang, May 13, 1993 */ /* wang@astro.temple.edu */ /* */ /* 200: Posting OK; 201: No posting */ /* */ /* Note: I DO NOT have the authorization to use them */ /* Using these services at your own risk */ /**********************************************************/ aardvark.ucs.uoknor.edu 201 ac.dal.ca 201 acad.drake.edu 201 acavax.lynchburg.edu 200 aqueous.ml.csiro.AU 200 bert.eecs.uic.edu 201 blaze.trentu.ca 201 bunyip.cc.uq.oz.au 201 buzzard.eecs.umich.edu 200 cc.ntnu.edu.tw 200 cc.usu.edu 201 ccds3.ntu.edu.tw 200 ccnews.nctu.edu.tw 200 ccsvax.sfasu.edu 200 ccvax.ucd.ie 200 cronkite.ocis.temple.edu 200 crux.rp.CSIRO.AU 200 csc.canberra.edu.au 201 csun.edu 200 cv3.cv.nrao.edu 200 dec8.ncku.edu.tw 200 desire.wright.edu 200 donau.et.tudelft.nl 200 emba-news.uvm.edu 201 embl-heidelberg.de 200 fac.cabot.nf.ca 200 falcon.aamrl.wpafb.af.mil 200 fang.dsto.gov.au 200 faraday.ece.cmu.edu 200 fission.dt.wdc.com 200 flash.pax.tpa.com.au 200 foxhound.dsto.gov.au 200 gaia.ucs.orst.edu 201 gmuvax.gmu.edu 201 gneiss.bmr.gov.au 200 grumpy.symantec.com 200 guardian.up.edu 201 hack.dragoman.com 201 hkuxb.hku.hk 201 hmcvax.claremont.edu 201 inca.comlab.ox.ac.uk 201 informatik.uni-koblenz.de 200 iris.resntl.bhp.com.au 201 iti.gov.sg 201 jabaru.cec.edu.au 200 jvnc.net 201 lambda.msfc.nasa.gov 201 SHAR_EOF fi # end of overwriting check if test -f 'wang.c' then echo shar: will not over-write existing file "'wang.c'" else cat << \SHAR_EOF > 'wang.c' /******************************************************************/ /* wang.c version 4.0 */ /* by Jonathan Wang, May 20, 1993 */ /* wang@astro.ocis.temple.edu */ /* */ /* USENET binary files download and assemble utility */ /* type wang -h for help */ /******************************************************************/ char nntpserver[255]= "128.8.10.5"; /*umd5.umd.edu*/ char newsgroup[255]= "alt.binaries.pictures.misc"; int index_start=0; int index_end=0; #include #include #include #include "nntplib.c" #define MAXFILES 2048 struct superblock { char Filename[255]; int Part; int Parts; int Article; /*char Newsgroup[255]; */ } Filereg[MAXFILES]; #define LEN 255 char line[LEN], buf[LEN]; int filecount=0; struct superblock nextfilereg(); /*************************************************************/ main(argc, argv) int argc; char *argv[]; { ArgumentProcess(argc, argv); puts("Warning: This program may generate up to 250 picture files."); puts(" i.e., appox. 20M disk space will be used."); puts("Please make appropriate preparation and inform your sysadm."); puts("FYI: The priority is lowered to +10\n"); nice(10); /* don't wanna sysadm freak out */ puts("setting up connection ..."); server_init(nntpserver, "nntp", 119); SubjectAnalysis(); Retrieve(); close_server(); }/* end of main */ /**********************************************************/ ArgumentProcess(argc, argv) int argc; char *argv[]; { int i; for (i=1; i59) && (strlen(buf) <71) ) ) { a[0]=b[0]='\0'; fprintf(to,"%s\n",buf); break; /* real stuff begins */ } } if (ret==-1) perror("cannot get_server at body command"); /* pipe everthing to uudecode */ while ( (ret=get_server(buf,LEN)) != -1) { if (strcmp(buf,".")==0) break; if (strncmp(buf, "end", 3) == 0) { if (b[0]) fprintf(to,"%s\n",b); if (a[0]) fprintf(to,"%s\n",a); fprintf(to,"%s\n",buf); } /* else if (strncmp(buf,"END", 3) == 0) break; */ else { len=strlen(buf); if ( (buf[0] != 'M' || len <60 || len >70 ) && (strncmp(buf,"begin ", 5)) ) { strcpy(b,a); strcpy(a,buf); continue; } a[0]=b[0]='\0'; fprintf(to,"%s\n",buf); } } /* end of 2nd while */ if (ret==-1) perror("get_server err 2nd at body command"); } /***************************************/ struct superblock nextfilereg() { int count; static struct superblock nulblock = { "\0", 0, 0, 0 }; for (count=1; count char word[LEN],oldword[LEN]; getinfo(buf) char *buf; { int t1,t2; filecount++; #ifdef DEBUG puts(buf); #endif if (GetArticleNumber(buf) == 0) fprintf(stderr,"get article number error: buf=%s",buf); if ( isRE(buf) ) { #ifdef DEBUG puts("Regarding ... -- TRASH"); #endif filecount--; /* don't want this into Filereg */ return; } t1=GetSubject(buf); t2=GetPartInfo(buf); if ( t1 && (Filereg[filecount].Part != 0) && (Filereg[filecount].Parts != 0) ) ; else if ( (!t1) && (Filereg[filecount].Part !=0 ) && (Filereg[filecount].Parts != 0) ) strcpy(Filereg[filecount].Filename, getword(buf)); else if ( t1 && ( !t2 ) ) /* for careless poster */ Filereg[filecount].Part= Filereg[filecount].Parts= 1; else { #ifdef DEBUG puts("part 0, or text file -- TRASH"); #endif filecount--; /* don't want this into Filereg */ return; } #ifdef DEBUG printf("\tarticle=%d, filename=%s, part= %d, parts=%d\n", Filereg[filecount].Article, Filereg[filecount].Filename, Filereg[filecount].Part, Filereg[filecount].Parts); #endif } /******************************************/ GetArticleNumber(buf) char *buf; { char tmp[LEN]; strcpy(tmp,getword(buf)); if (!isnumber(tmp)) return(0); else { Filereg[filecount].Article=atoi(tmp); return(1); } } /******************************************/ GetSubject(buf) char *buf; { char line[LEN]; strcpy(line,buf); /* don't wanna destroy buf */ do { strcpy(word,getword(line)); if ( (word[0] == '.') && isstring(oldword) && isstring(peekword(line)) ) { sprintf(Filereg[filecount].Filename,"%s.%s",oldword,getword(line)); return(1); } strcpy(oldword,word); }while (word[0]!='\0'); return(0); } /**********************************************/ GetPartInfo(buf) char *buf; { char line[LEN]; strcpy(line,buf); do { strcpy(word,getword(line)); if ( ( (word[0] == '/') || (strcmp(word,"of") == 0)) && isnumber(oldword) && isnumber(peekword(line)) ) { Filereg[filecount].Part=atoi(oldword); Filereg[filecount].Parts=atoi(getword(line)); return(1); } strcpy(oldword,word); }while (word[0]!='\0'); return(0); } /*****************************************/ getword(line) char *line; { int i; char backup[LEN]; char tmp; if (line[0] == '\0') /* is it empty? -- different machines treat isspace differently */ return("\0"); strcpy(backup,line); if (isspace(backup[0])) /* space? ignor */ strcpy(backup,line+1); if (backup[0] == '\0') /* is it empty ? */ return("\0"); if (!isalnum(backup[0])) /* begin with non alnum? return it */ { strcpy(line,backup+1); backup[1]='\0'; return(backup); } for (i=0; backup[i] != '\0'; i++) { if (!isalnum(backup[i])) { strcpy(line,backup+i); backup[i]='\0'; return(backup); } else if (isupper(backup[i])) { tmp=tolower(backup[i]); backup[i]=tmp; } } line[0]='\0'; return (backup); } /***********************************************/ peekword(line) char *line; { int i; char backup[LEN]; char tmp; if (line[0] == '\0') return("\0"); strcpy(backup,line); if (isspace(backup[0])) /* space? ignore */ strcpy(backup,line+1); if (backup[0] == '\0') return("\0"); if (!isalnum(backup[0])) { backup[i]='\0'; return(backup); } for (i=0; backup[i]!='\0' ;i++) if (!isalnum(backup[i])) { backup[i]='\0'; return(backup); } else if (isupper(backup[i])) { tmp=tolower(backup[i]); backup[i]=tmp; } return(backup); } /**************************************************/ int isstring(string) char *string; { int i; for (i=0;i