This is nntpxfer.c in view mode; [Download] [Up]
#ifndef lint static char * scsid = "@(#)$Header: nntpxfer.c,v 1.9 91/02/02 13:31:37 sob Exp $"; #endif /* * nntpxfer * * Connects to the specified nntp server, and transfers all new news * since the last successful invocation. * * last successful invocation date and time are stored in a file at * /usr/spool/news/nntp.<hostname> as * groups YYMMDD HHMMSS distributions\n * in case you need to edit it. You can also override this on * the command line in the same format, in which case the file won't * be updated. * * Brian Kantor, UCSD 1986 * (some bug fixes by ambar@athena.mit.edu) * Modified to use NNTP distribution conf.h file and nntpxmit's get_tcp_conn.c * subroutines so that nntpxfer could be used on more systems. * Stan Barber, November 7, 1989 <sob@bcm.tmc.edu> * */ #include "../common/conf.h" #ifdef DEBUG #undef SYSLOG #endif #include <sys/types.h> #ifdef NDIR #ifdef M_XENIX #include <sys/ndir.h> #else #include <ndir.h> #endif #else #include <sys/dir.h> #endif #ifdef USG #include <time.h> #else #include <sys/time.h> #endif #include <stdio.h> #include <errno.h> #include <ctype.h> #include <setjmp.h> #ifndef NONETDB #include <netdb.h> #endif #include <signal.h> #ifdef SYSLOG #ifdef FAKESYSLOG #include "../server/fakesyslog.h" #else #include <syslog.h> #endif #endif #ifdef DBM # ifdef DBZ # include <dbz.h> #else /* DBZ */ # undef NULL # include <dbm.h> # undef NULL # define NULL 0 #endif /* DBZ */ #endif /* DBM */ #ifdef NDBM #include <ndbm.h> #include <fcntl.h> static DBM *db = NULL; #endif #ifndef TIMEOUT #define TIMEOUT (30*60) #endif #ifndef MAX_ARTICLES #define MAX_ARTICLES 4096 #endif char *malloc(); char *strcpy(); char *strcat(); char *rindex(); long time(); u_long inet_addr(); extern int errno; char *artlist[MAX_ARTICLES]; int server; /* stream socket to the nntp server */ FILE * rd_fp, * wr_fp; int newart, dupart, misart; char * Pname; main(argc, argv) int argc; char *argv[]; { FILE *dtfile; /* where last xfer date/time stored */ char buf[BUFSIZ]; char lastdate[16]; char distributions[BUFSIZ]; char dtname[128]; char newsgroups[BUFSIZ]; char lasttime[16]; int i; int omitupdate = 0; /* 1 = don't update datetime */ long clock; long newdate, newtime; struct tm *now; Pname = ((Pname = rindex(argv[0], '/')) ? Pname + 1 : argv[0]); /* OPTIONS argv[1] MUST be the host name argv[2-4] MAY be "newsgroups YYMMDD HHMMSS" argv[5] MAY be distributions (otherwise use 2-4/5 from the file "/usr/spool/news/nntp.hostname") */ if (argc != 2 && argc != 5 && argc != 6) { (void) printf("Usage: %s host [groups YYMMDD HHMMSS [<dist>]]\n", argv[0]); exit(1); } if (argc > 2) { omitupdate=1; (void) strcpy(newsgroups, argv[2]); (void) strcpy(lastdate, argv[3]); (void) strcpy(lasttime, argv[4]); (void) strcpy(distributions, ""); if (argc > 5) (void) strcpy(distributions, argv[5]); } else { (void) sprintf(dtname, "%s/nntp.%s",SPOOLDIR,argv[1]); dtfile = fopen(dtname, "r"); if (dtfile == (FILE *) 0) { (void) printf("%s not found; using * 860101 000000 \n", dtname); (void) strcpy(newsgroups, "*"); (void) strcpy(lastdate, "860101"); (void) strcpy(lasttime, "000000"); (void) strcpy(distributions, ""); } else { if (fscanf(dtfile, "%s %s %s %s", newsgroups, lastdate, lasttime, distributions) < 3) { (void) printf("%s invalid; using * 860101 000000\n", dtname); (void) strcpy(newsgroups, "*"); (void) strcpy(lastdate, "860101"); (void) strcpy(lasttime, "000000"); (void) strcpy(distributions, ""); } (void) fclose(dtfile); } clock = time((long *)0); now = gmtime(&clock); newdate = (now->tm_year * 10000) + ((now->tm_mon + 1) * 100) + now->tm_mday; newtime = (now->tm_hour * 10000) + (now->tm_min * 100) + now->tm_sec; #ifdef DEBUG printf("server is %s\n",argv[1]); printf("lastdate is %s\n",lastdate); printf("lasttime is %s\n",lasttime); printf("newsgroups is '%s'\n",newsgroups); printf("distributions is '%s'\n",distributions); #endif } #ifdef SYSLOG #ifdef BSD_42 openlog("nntpxfer", LOG_PID); #else openlog("nntpxfer", LOG_PID, SYSLOG); #endif #endif #ifdef DBM if (dbminit(HISTORY_FILE) < 0) { #ifdef SYSLOG syslog(LOG_ERR,"couldn't open history file: %m"); #else perror("nntpxfer: couldn't open history file"); #endif exit(1); } #endif #ifdef NDBM if ((db = dbm_open(HISTORY_FILE, O_RDONLY, 0)) == NULL) { #ifdef SYSLOG syslog(LOG_ERR,"couldn't open history file: %m"); #else perror("nntpxfer: couldn't open history file"); #endif exit(1); } #endif if ((server = get_tcp_conn(argv[1],"nntp")) < 0) { #ifdef SYSLOG syslog(LOG_ERR,"could not open socket: %m"); #else perror("nntpxfer: could not open socket"); #endif exit(1); } if ((rd_fp = fdopen(server,"r")) == (FILE *) 0){ #ifdef SYSLOG syslog(LOG_ERR,"could not fdopen socket: %m"); #else perror("nntpxfer: could not fdopen socket"); #endif exit(1); } #ifdef SYSLOG syslog(LOG_DEBUG,"connected to nntp server at %s", argv[1]); #endif #ifdef DEBUG printf("connected to nntp server at %s\n", argv[1]); #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 (void) printf("%s\n", buf); #endif if (buf[0] != '2') /* uh-oh, something's wrong! */ { #ifdef SYSLOG syslog(LOG_NOTICE,"protocol error: got '%s'\n", buf); #else (void) printf("%s: protocol error: got '%s'\n", Pname,buf); #endif (void) close(server); exit(1); } /* first, tell them we're a slave process to get priority */ sockwrite("SLAVE"); (void) sockread(buf); #ifdef DEBUG (void) printf("%s\n", buf); #endif if (buf[0] != '2') /* uh-oh, something's wrong! */ { #ifdef SYSLOG syslog(LOG_NOTICE,"protocol error: got '%s'", buf); #else (void) printf("%s: protocol error: got '%s'\n", Pname,buf); #endif (void) close(server); exit(1); } /* now, ask for a list of new articles */ if (strlen(distributions)) (void) sprintf(buf,"NEWNEWS %s %s %s GMT <%s>", newsgroups, lastdate, lasttime, distributions); else (void) sprintf(buf,"NEWNEWS %s %s %s GMT", newsgroups, lastdate, lasttime); sockwrite(buf); (void) sockread(buf); #ifdef DEBUG (void) printf("%s\n", buf); #endif if (buf[0] != '2') /* uh-oh, something's wrong! */ { #ifdef SYSLOG syslog(LOG_NOTICE,"protocol error: got '%s'", buf); #else (void) printf("%s: protocol error: got '%s'\n", Pname,buf); #endif (void) close(server); exit(1); } /* and here comes the list, terminated with a "." */ #ifdef DEBUG (void) printf("data\n"); #endif dupart = newart = 0; while (1) { (void) sockread(buf); if (!strcmp(buf,".")) break; if (wewant(buf)) { if (newart >= MAX_ARTICLES) { omitupdate=1; continue; } artlist[newart] = malloc((unsigned)(strlen(buf)+1)); (void) strcpy(artlist[newart], buf); newart++; } else dupart++; } #ifdef DEBUG (void) printf(".\n%d new, %d dup articles\n", newart, dupart); #endif /* now that we know which articles we want, retrieve them */ for (i=0; i < newart; i++) (void) artfetch(artlist[i]); #ifdef DEBUG (void) printf("%d missing articles\n", misart); #endif /* we're all done, so tell them goodbye */ sockwrite("QUIT"); (void) sockread(buf); #ifdef DEBUG (void) printf("%s\n", buf); #endif if (buf[0] != '2') /* uh-oh, something's wrong! */ { #ifdef SYSLOG syslog(LOG_NOTICE,"error: got '%s'", buf); #else (void) printf("%s: error: got '%s'\n", Pname,buf); #endif (void) close(server); exit(1); } (void) close(server); /* do we want to update the timestamp file? */ if (!omitupdate) { (void) sprintf(buf, "%s %06d %06d %s\n", newsgroups, newdate, newtime, distributions); #ifdef DEBUG (void) printf("updating %s:\n\t%s\n", dtname, buf); #endif dtfile = fopen(dtname, "w"); if (dtfile == (FILE *) 0) { perror(dtname); exit(1); } (void) fputs(buf,dtfile); (void) fclose(dtfile); } exit(0); } artfetch(articleid) char *articleid; { #ifdef DEBUG int lines = 0; #endif char buf[BUFSIZ]; FILE *inews; /* now, ask for the article */ (void) sprintf(buf,"ARTICLE %s", articleid); sockwrite(buf); (void) sockread(buf); #ifdef DEBUG (void) printf("%s\n", buf); #endif if (buf[0] == '4') /* missing article, just skipit */ { misart++; return(0); } if (buf[0] != '2') /* uh-oh, something's wrong! */ { #ifdef SYSLOG syslog(LOG_NOTICE,"protocol error: got '%s'", buf); #else (void) printf("%s: protocol error: got '%s'\n", Pname, buf); #endif (void) close(server); exit(1); } #ifdef DEBUG (void) printf("command: %s\n", RNEWS); #endif if ( (inews = popen(RNEWS, "w")) == (FILE *) 0) { perror(RNEWS); exit(1); } /* and here comes the article, terminated with a "." */ #ifdef DEBUG (void) printf("data\n"); #endif while (1) { (void) sockread(buf); if (buf[0] == '.' && buf[1] == '\0') break; #ifdef DEBUG lines++; #endif (void) strcat(buf,"\n"); (void) fputs(((buf[0] == '.') ? buf + 1 : buf), inews); } #ifdef DEBUG (void) printf(".\n%d lines\n", lines); #endif (void) fflush(inews); (void) pclose(inews); return(0); } static jmp_buf SFGstack; static SIGRET to_sfgets() { longjmp(SFGstack, 1); } int sockread(buf) char *buf; { int esave, rz; char * ret; if (setjmp(SFGstack)) { (void) alarm(0); /* reset alarm clock */ (void) signal(SIGALRM, SIG_DFL); rd_fp->_flag |= _IOERR; /* set stdio error */ #ifndef ETIMEDOUT errno = EPIPE; /* USG doesn't have ETIMEDOUT */ #else errno = ETIMEDOUT; /* connection timed out */ #endif #ifdef SYSLOG syslog(LOG_ERR,"nntpxfer: read error on server socket: %m"); #else (void) perror("nntpxfer: read error on server socket"); #endif (void) close(server); exit(1); } (void) signal(SIGALRM, to_sfgets); (void) alarm(TIMEOUT); ret = fgets(buf, BUFSIZ, rd_fp); esave = errno; (void) alarm(0); /* reset alarm clock */ (void) signal(SIGALRM, SIG_DFL); /* reset SIGALRM */ errno = esave; rz = strlen(buf); buf[rz-2] = '\0'; if (ret == (char * ) 0) { #ifdef SYSLOG syslog(LOG_ERR,"nntpxfer: read error on server socket: %m"); #else (void) perror("nntpxfer: read error on server socket"); #endif (void) fclose(rd_fp); exit(1); } return(0); } sockwrite(buf) char *buf; { register int sz; char buf2[BUFSIZ]; #ifdef DEBUG (void) printf(">>> %s\n", buf); #endif (void) strcpy(buf2,buf); (void) strcat(buf2,"\r\n"); sz = strlen(buf2); if (write(server,buf2,sz) != sz) { #ifdef SYSLOG syslog(LOG_ERR,"nntpxfer: write error on server socket"); #else (void) printf("nntpxfer: write error on server socket\n"); #endif (void) close(server); exit(1); } } int wewant(articleid) char *articleid; { #if defined(DBM) || defined(NDBM) datum k, d; #else FILE *k; char *histfile(); FILE *histfp; /* USG history file */ char line[BUFSIZ]; int len; #endif char id[BUFSIZ]; char *p; /* remove any case sensitivity */ (void) strcpy(id, articleid); p = id; #ifndef CNEWS while (*p) { if (isupper(*p)) *p = tolower(*p); p++; } #endif #if defined(DBM) || defined(NDBM) k.dptr = id; k.dsize = strlen(articleid) + 1; #ifdef DBM d = fetch(k); #else d = dbm_fetch(db, k); #endif if (d.dptr) { #ifdef DEBUG (void) printf("dup: '%s'\n", articleid); #endif return(0); } #ifdef DEBUG (void) printf("new: '%s'\n", articleid); #endif return(1); #else histfp = fopen(histfile(articleid), "r"); if (histfp == NULL) { #ifdef DEBUG (void) printf("new: '%s'\n", articleid); #endif return(1); } len = strlen(articleid); while (fgets(line, sizeof (line), histfp)) if (!strncmp(articleid, line, len)) break; if (feof(histfp)) { (void) fclose(histfp); #ifdef DEBUG (void) printf("new: '%s'\n", articleid); #endif return (1); } (void) fclose(histfp); #ifdef DEBUG (void) printf("dup: '%s' %s\n", articleid,line); #endif return(0); #endif } #ifdef USGHIST /* ** Generate the appropriate history subfile name */ char * histfile(hline) char *hline; { char chr; /* least significant digit of article number */ static char subfile[BUFSIZ]; chr = findhfdigit(hline); sprintf(subfile, "%s.d/%c", HISTORY_FILE, chr); return subfile; } findhfdigit(fn) char *fn; { register char *p; register int chr; extern char * index(); p = index(fn, '@'); if (p != NULL && p > fn) chr = *(p - 1); else chr = '0'; if (!isdigit(chr)) chr = '0'; return chr; } #endif char * errmsg(code) int code; { extern int sys_nerr; extern char *sys_errlist[]; static char ebuf[6+5+1]; if (code > sys_nerr || code < 0) { (void) sprintf(ebuf, "Error %d", code); return ebuf; } else return sys_errlist[code]; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.