nntp
Russ Nelson
nelson at sun.soe.clarkson.edu
Fri Jul 14 06:00:18 AEST 1989
/*
* nntp
*
* Connects to the specified nntp server. Sends standard input to it,
* and sends output to standard output as needed.
*
* Written by Russell Nelson, 7-13-89. No copyright claimed.
* Based on nntpxfer by:
* Brian Kantor, UCSD 1986
* (some bug fixes by ambar at athena.mit.edu)
*
* put it in nntp.1.5/nntp/nntp.c and compile.
*
* usage: nntp host command arguments
*
* example: nntp host sun.soe.clarkson.edu newnews alt.sources 890713 000000
*
*/
#define DEBUG
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <netdb.h>
#include <signal.h>
#include "../common/nntp.h"
char *malloc();
char *strcpy();
char *strcat();
u_long inet_addr();
extern int errno;
int server; /* stream socket to the nntp server */
int debug=0; /* true if we're debugging. */
main(argc, argv)
int argc;
char *argv[];
{
char buf[BUFSIZ];
int connected = 0; /* 1 = connected */
int i;
int omitupdate = 0; /* 1 = don't update datetime */
struct hostent *hp;
struct servent *sp;
struct sockaddr_in sin;
char *hostname;
# define SKIPARG while (*++(*argv)); --(*argv)
# define CLRARG strncpy (*argv, BLANKS, strlen (*argv)); \
while (*++(*argv)); --(*argv)
#define USAGE "usage: nntp [-d] [-d] [-hhostname] nntp-command"
hostname = NULL;
while (--argc > 0 && (*++argv)[0] == '-'){
while (*++(*argv)){
switch (**argv){
#if 0
case 'h':
hostname = argv+1;
SKIPARG;
break;
#endif
case 'd':
debug++;
break;
default:
fprintf (stderr, "%s\n", USAGE);
exit (1);
}
}
}
if (!hostname)
hostname = *argv++;
sin.sin_addr.s_addr = inet_addr(hostname);
if (sin.sin_addr.s_addr != -1)
{
sin.sin_family = AF_INET;
}
else
{
hp = gethostbyname(hostname);
if (hp == NULL)
{
(void) printf("%s: unknown host\n", hostname);
exit(1);
}
sin.sin_family = hp->h_addrtype;
#ifdef BSD43
bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr,
hp->h_length);
#else BSD43
bcopy(hp->h_addr, (caddr_t)&sin.sin_addr,
hp->h_length);
#endif BSD43
}
sp = getservbyname("nntp", "tcp");
if (sp == NULL)
{
perror("nntp/tcp");
exit(1);
}
sin.sin_port = sp->s_port;
do {
server = socket(AF_INET, SOCK_STREAM, 0);
if (server < 0)
{
perror("nntpxfer: socket");
exit(1);
}
if (connect(server, (struct sockaddr *)&sin, sizeof (sin)) < 0)
{
#ifdef BSD43
if (hp && hp->h_addr_list[1])
{
hp->h_addr_list++;
bcopy(hp->h_addr_list[0],
(caddr_t)&sin.sin_addr, hp->h_length);
(void) close(server);
continue;
}
#endif BSD43
perror("nntpxfer: connect");
exit(1);
}
connected++;
}
while (connected == 0);
#ifdef DEBUG
if(debug)
(void) printf("connected to nntp server at %s\n", hostname);
#endif
/*
* ok, at this point we're connected to the nntp daemon
* at the distant host.
*/
/* get the greeting herald */
(void) sockread(buf);
#ifdef DEBUG
if(debug)
(void) printf("%s\n", buf);
#endif
if (buf[0] != '2') /* uh-oh, something's wrong! */
{
(void) printf("protocol error: got '%s'\n", buf);
(void) close(server);
exit(1);
}
/* first, tell them we're a slave process to get priority */
sockwrite("SLAVE");
(void) sockread(buf);
#ifdef DEBUG
if(debug)
(void) printf("%s\n", buf);
#endif
if (buf[0] != '2') /* uh-oh, something's wrong! */
{
(void) printf("protocol error: got '%s'\n", buf);
(void) close(server);
exit(1);
}
/* now, build their command and send it */
strcpy(buf, "");
while (*argv) {
strcat(buf, *argv++);
if (*argv)
strcat(buf, " ");
}
sockwrite(buf);
(void) sockread(buf);
#ifdef DEBUG
if(debug)
(void) printf("%s\n", buf);
#endif
/* now we see if we need to read from stdin or write to stdout */
switch(atoi(buf)){
case INF_HELP:
case OK_GROUPS:
case OK_ARTICLE:
case OK_HEAD:
case OK_BODY:
case OK_NEWNEWS:
case OK_NEWGROUPS:
#ifdef DEBUG
if(debug)
(void) printf("receive data\n");
#endif
for(;;){
(void) sockread(buf);
if (buf[0] == '.' && buf[1] == '\0')
break;
(void) strcat(buf,"\n");
(void) fputs(((buf[0] == '.') ? buf + 1 : buf),
stdout);
}
break;
case CONT_XFER:
case CONT_POST:
#ifdef DEBUG
if(debug)
(void) printf("send data\n");
#endif
buf[0] = '.';
while (gets(buf+1)){
(void) sockwrite(((buf[1] == '.') ? buf : buf + 1));
}
sockwrite(".");
break;
}
/* we're all done, so tell them goodbye */
sockwrite("QUIT");
(void) sockread(buf);
#ifdef DEBUG
if(debug)
(void) printf("%s\n", buf);
#endif
if (buf[0] != '2'){ /* uh-oh, something's wrong! */
(void) printf("error: got '%s'\n", buf);
(void) close(server);
exit(1);
}
(void) close(server);
exit(0);
}
int
sockread(buf)
char *buf;
{
char c;
int j = 0;
#ifdef BSD43
fd_set rf;
#else BSD43
int rf;
#endif BSD43
struct timeval tv;
int r;
char *p = buf;
for (;;){
tv.tv_sec = 1800; /* 15 minutes */
tv.tv_usec = 0L;
#ifdef BSD43
FD_ZERO(&rf);
FD_SET(server, &rf);
#else BSD43
rf = 1 << server;
#endif BSD43
r = select(20, (fd_set *)&rf, (fd_set *)0, (fd_set *)&rf, &tv);
if (r < 0){
if (errno == EINTR)
continue;
perror("getsock select");
exit(1);
}
if (r == 0){
printf("read timed out.\n");
exit(1);
}
if (read(server, &c, 1) <= 0)
break;
/* mask off any chance parity bits */
*p = c & 0x7f;
/* look for end of line (== LF) */
if (c == 0x0a){
if (j > 0 && *(p-1) == 0x0d)
*(p-1) = '\0';
else
*p = '\0';
#ifdef DEBUG
if(debug > 1)
(void) printf("<<< %s\n", buf);
#endif
return(strlen(buf));
}
j++; p++;
}
perror("sockread");
(void) close(server);
exit(1);
/* NOTREACHED */
}
sockwrite(buf)
char *buf;
{
register int sz;
char buf2[BUFSIZ];
#ifdef DEBUG
if(debug > 1)
(void) printf(">>> %s\n", buf);
#endif
(void) strcpy(buf2,buf);
(void) strcat(buf2,"\r\n");
sz = strlen(buf2);
if (write(server,buf2,sz) != sz){
(void) printf("write error on server socket\n");
(void) close(server);
exit(1);
}
}
--
--russ (nelson at clutx [.bitnet | .clarkson.edu])
I'm not the NRA, and I vote twice.
More information about the Alt.sources
mailing list