/* Usage: bbsnnrp [options] nntpserver activefile -h|? (help) -v (verbose protocol transactions) -c (reset active files only; don't receive articles) -r remotehost(send articles to remotehost, default=local) -p port|(send articles to remotehost at port, default=7777) path(send articles to local at path, default=~bbs/innd/.innbbsd) -n (don't ask innbbsd server and stat articles) -w seconds (wait for seconds and run infinitely, default=once) -a max_art (maximum number of articles received for a group each time) -s max_stat(maximum number of articles stated for a group each time) -t stdin|nntp (default=nntp) */ #include "innbbsconf.h" #include #ifndef AIX # include #endif #include "bbslib.h" #include "daemon.h" #include "nntp.h" #ifndef MAX_ARTS # define MAX_ARTS 100 #endif #ifndef MAX_STATS # define MAX_STATS 1000 #endif #if defined(__linux) #define NO_USE_MMAP #else #define USE_MMAP #endif int Max_Arts= MAX_ARTS; int Max_Stats = MAX_STATS; typedef struct NEWSRC_T { char *nameptr, *lowptr, *highptr, *modeptr; int namelen, lowlen, highlen; ULONG low, high; int mode, subscribe; } newsrc_t; typedef struct NNRP_T { int nnrpfd; int innbbsfd; FILE *nnrpin, *nnrpout; FILE *innbbsin, *innbbsout; char activefile[MAXPATHLEN]; char rcfile[MAXPATHLEN]; newsrc_t *newsrc; char *actpointer, *actend; int actsize, actfd, actdirty; } nnrp_t; typedef struct XHDR_T { char *header; ULONG artno; } xhdr_t; xhdr_t XHDR[MAX_ARTS]; char LockFile[1024]; #define NNRPGroupOK NNTP_GROUPOK_VAL #define NNRPXhdrOK NNTP_HEAD_FOLLOWS_VAL #define NNRParticleOK NNTP_ARTICLE_FOLLOWS_VAL #define INNBBSstatOK NNTP_NOTHING_FOLLOWS_VAL #define INNBBSihaveOK NNTP_SENDIT_VAL #define NNRPconnectOK NNTP_POSTOK_VAL #define NNRPstatOK NNTP_NOTHING_FOLLOWS_VAL #define INNBBSconnectOK NNTP_POSTOK_VAL nnrp_t BBSNNRP; void doterm(s) int s; { printf("bbsnnrp terminated. Signal %d\n", s); writerc(&BBSNNRP); if (isfile(LockFile)) unlink(LockFile); exit(1); } extern char *optarg; extern int opterr, optind; #ifndef MIN_WAIT # define MIN_WAIT 60 #endif int ResetActive = 0; int StatHistory = 1; int AskLocal = 1; int RunOnce = 1; int DefaultWait = MIN_WAIT; char *DefaultPort = DefaultINNBBSPort; char *DefaultPath = LOCALDAEMON; char *DefaultRemoteHost; #ifndef MAXBUFLEN #define MAXBUFLEN 256 #endif char DefaultNewsgroups[MAXBUFLEN]; char DefaultOrganization[MAXBUFLEN]; char DefaultModerator[MAXBUFLEN]; char DefaultTrustfrom[MAXBUFLEN]; char DefaultTrustFrom[MAXBUFLEN]; usage(arg) char *arg; { fprintf(stderr,"Usage: %s [options] nntpserver activefile\n", arg); fprintf(stderr," -h|? (help) \n"); fprintf(stderr," -v (verbose protocol transactions)\n"); fprintf(stderr," -c (reset active files only; don't receive articles)\n"); fprintf(stderr," -r [proto:]remotehost\n"); fprintf(stderr," (send articles to remotehost, default=ihave:local)\n"); fprintf(stderr," -p port|(send articles to remotehost at port, default=%s)\n",DefaultINNBBSPort); fprintf(stderr," path(send articles to local at path, default=~bbs/innd/.innbbsd)\n"); fprintf(stderr," -w seconds ( > 1 wait for seconds and run infinitely, default=once)\n"); fprintf(stderr," -n (don't ask innbbsd server and stat articles)\n"); fprintf(stderr," -a max_art(maximum number of articles received for a group each time)\n"); fprintf(stderr," default=%d\n", MAX_ARTS); fprintf(stderr," -s max_stat(maximum number of articles stated for a group each time)\n"); fprintf(stderr," default=%d\n", MAX_STATS); fprintf(stderr," -t stdin|nntp (default=nntp)\n"); fprintf(stderr," -g newsgroups\n"); fprintf(stderr," -m moderator\n"); fprintf(stderr," -o organization\n"); fprintf(stderr," -f trust_user (From: trust_user)\n"); fprintf(stderr," -F trust_user (From trust_user)\n"); fprintf(stderr," Please E-mail bug to skhuang@csie.nctu.edu.tw or\n"); fprintf(stderr," post to tw.bbs.admin.installbbs\n"); } static char *StdinInputType="stdin"; static char *NntpInputType="nntp"; static char *NntpIhaveProtocol="ihave"; static char *NntpPostProtocol="post"; static char *DefaultNntpProtocol ; main(argc, argv) int argc; char **argv; { char *ptr, *server, *active; int c, errflag=0; int lockfd; char *inputtype; DefaultNntpProtocol = NntpIhaveProtocol; *DefaultNewsgroups = '\0'; *DefaultModerator = '\0'; *DefaultOrganization = '\0'; *DefaultTrustFrom = '\0'; *DefaultTrustfrom = '\0'; inputtype = NntpInputType; while ((c = getopt(argc,argv,"f:F:m:o:g:w:r:p:a:s:t:h?ncv"))!= -1) switch (c) { case 'v': verboseon("bbsnnrp.log"); break; case 'c': ResetActive = 1; break; case 'g': strncpy(DefaultNewsgroups, optarg, sizeof DefaultNewsgroups); break; case 'm': strncpy(DefaultModerator, optarg, sizeof DefaultModerator); break; case 'o': strncpy(DefaultOrganization, optarg, sizeof DefaultOrganization); break; case 'f': strncpy(DefaultTrustfrom, optarg, sizeof DefaultTrustfrom); break; case 'F': strncpy(DefaultTrustFrom, optarg, sizeof DefaultTrustFrom); break; case 'r': { char *hostptr; AskLocal = 0; DefaultRemoteHost = optarg; if ((hostptr = strchr(optarg,':')) != NULL) { *hostptr = '\0'; DefaultRemoteHost = hostptr+1; if (strcasecmp( optarg, "post" ) == 0) DefaultNntpProtocol = NntpPostProtocol; *hostptr = ':'; } break; } case 'w': RunOnce = 0; DefaultWait = atoi(optarg); if (DefaultWait < MIN_WAIT) DefaultWait = MIN_WAIT; break; case 'p': if (AskLocal == 0) { DefaultPort = optarg; } else { DefaultPath = optarg; } break; case 'n': StatHistory = 0; break; case 'a': Max_Arts = atol(optarg); if (Max_Arts < 0) Max_Arts = 0; break; case 's': Max_Stats = atol(optarg); if (Max_Stats < 0) Max_Stats = 0; break; case 't': if ( strcasecmp(optarg,StdinInputType) == 0) { inputtype = StdinInputType; } break; case 'h': case '?': default: errflag ++; } if (errflag > 0) { usage(argv[0]); return(1); } if (inputtype == NntpInputType && argc - optind < 2) { usage(argv[0]); exit(1); } if (inputtype == NntpInputType) { server = argv[optind]; active = argv[optind+1]; if ( isfile(active) ) { strncpy(BBSNNRP.activefile, active, sizeof BBSNNRP.activefile); } else if ( strchr(active,'/') == NULL) { sprintf(BBSNNRP.activefile, "%s/innd/%.*s",BBSHOME, sizeof BBSNNRP.activefile - 7 - strlen(BBSHOME), active); } else { strncpy(BBSNNRP.activefile, active, sizeof BBSNNRP.activefile); } strncpy(LockFile , (char*)fileglue("%s.lock",active), sizeof LockFile); if ((lockfd = open(LockFile, O_RDONLY)) >= 0) { char buf[10]; int pid; if (read(lockfd, buf, sizeof buf) > 0 && (pid = atoi(buf))>0 && kill(pid,0)==0) { fprintf(stderr, "another process [%d] running\n", pid); exit(1); } else { fprintf(stderr, "no process [%d] running, but lock file existed, unlinked\n", pid); unlink(LockFile); } close(lockfd); } if ((lockfd = open(LockFile, O_RDWR|O_CREAT|O_EXCL,0644)) < 0) { fprintf( stderr, "maybe another %s process running\n",argv[0]); exit(1); } else { char buf[10]; int pid; sprintf(buf,"%-.8d\n",getpid()); write(lockfd, buf, strlen(buf)); close(lockfd); } for (;;) { if (!initial_bbs(NULL)) { fprintf(stderr, "Initial BBS failed\n"); exit(1); } initsockets(server, &BBSNNRP, inputtype); ptr = (char*)strrchr(active,'/'); if (ptr != NULL) ptr++; else ptr = active; sprintf(BBSNNRP.rcfile,"%s/.newsrc.%s.%s",INNDHOME, server, ptr); initrcfiles(&BBSNNRP); signal(SIGTERM, doterm); signal(SIGKILL, doterm); signal(SIGHUP, doterm); signal(SIGPIPE, doterm); readnews(server, &BBSNNRP); writerc(&BBSNNRP); closesockets(); if (RunOnce) break; sleep(DefaultWait); } unlink(LockFile); } /* NntpInputType */ else { if (!initial_bbs(NULL)) { fprintf(stderr, "Initial BBS failed\n"); exit(1); } initsockets(server, &BBSNNRP, inputtype); signal(SIGTERM, doterm); signal(SIGKILL, doterm); signal(SIGHUP, doterm); signal(SIGPIPE, doterm); stdinreadnews(&BBSNNRP); closesockets(); } /* stdin input type */ return 0; } headbegin(buffer) char *buffer; { if (strncmp(buffer,"Path: ",6)==0 ) { if (strchr(buffer+6,'!') != NULL) return 1; } if (strncmp(buffer,"From ",5)== 0 ) { if (strchr(buffer+5,':') != NULL) return 1; } return 0; } stdinreadnews(bbsnnrp) nnrp_t *bbsnnrp; { int i; char buffer[4096]; ULONG low, high; char tmpfilename[MAXPATHLEN]; FILE *tmpfp = NULL; char mid[1024]; int pathagain; int ngmet, submet, midmet, pathmet, orgmet, approvedmet; int discard; char sending_path[MAXPATHLEN]; int sending_path_len=0; strncpy(tmpfilename,(char*)fileglue("/tmp/bbsnnrp-stdin-%d-%d",getuid(),getpid()),sizeof tmpfilename); fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); verboselog("innbbsGet: %s", buffer); if (atoi(buffer) != INNBBSconnectOK) { fprintf(stderr, "INNBBS server not OK\n"); return; } if ( DefaultNntpProtocol == NntpPostProtocol ) { fputs("MODE READER\r\n", bbsnnrp->innbbsout); fflush(bbsnnrp->innbbsout); verboselog("innbbsPut: MODE READER\n"); fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); verboselog("innbbsGet: %s",buffer); } if (StatHistory == 0) { fputs("MIDCHECK OFF\r\n", bbsnnrp->innbbsout); fflush(bbsnnrp->innbbsout); verboselog("innbbsPut: MIDCHECK OFF\n"); fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); verboselog("innbbsGet: %s",buffer); } tmpfp = fopen(tmpfilename,"w"); if (tmpfp == NULL) return; *mid = '\0'; for (;;) { fprintf(stderr,"Try to read from stdin ...\n"); ngmet = 0, submet = 0, midmet = 0, pathmet = 0, orgmet = 0, approvedmet=0; discard = 0; while (fgets(buffer, sizeof buffer, stdin) != NULL) { char *tmpptr; tmpptr = strchr(buffer,'\n'); if (tmpptr != NULL) *tmpptr = '\0'; if (strncasecmp(buffer,"Message-ID: ",12)==0) { strncpy(mid, buffer+12,sizeof mid); midmet = 1; } else if (strncmp(buffer,"Subject: ",9)==0) { submet = 1; } else if (strncmp(buffer,"Path: ",6)==0) { pathmet = 1; } else if (strncmp(buffer,"Organization: ",14)==0) { orgmet = 1; } else if (strncmp(buffer,"Approved: ",10) == 0) { approvedmet = 1; } else if (strncmp(buffer,"From: ",6)==0 && *DefaultTrustfrom ) { if (strstr(buffer+6, DefaultTrustfrom)==NULL) { discard = 1; verboselog("Discard: %s for %s",buffer, DefaultTrustfrom); } } else if (strncmp(buffer,"From ",5)==0 && *DefaultTrustFrom ) { if (strstr(buffer+5, DefaultTrustFrom)==NULL) { discard = 1; verboselog("Discard: %s for %s",buffer, DefaultTrustFrom); } } else if (strncmp(buffer,"Received: ",10)==0) { char *rptr=buffer+10, *rrptr; int savech, len; if (strncmp(buffer+10,"from ",5)==0) { rptr +=5; rrptr = strchr(rptr,'('); if (rrptr != NULL) rptr = rrptr + 1; rrptr = strchr(rptr,' '); savech = *rrptr; if (rrptr != NULL) *rrptr = '\0'; } else if (strncmp(buffer+10,"(from ",6)==0) { rptr +=6; rrptr = strchr(rptr,')'); savech = *rrptr; if (rrptr != NULL) *rrptr = '\0'; } len = strlen(rptr) +1; if (*rptr && sending_path_len + len < sizeof(sending_path)) { if (*sending_path) strcat(sending_path, "!"); strcat(sending_path, rptr); sending_path_len += len ; } if (rrptr != NULL) *rrptr = savech; } if (strncmp(buffer,"Newsgroups: ",12)==0) { if (*DefaultNewsgroups){ fprintf(tmpfp,"Newsgroups: %s\r\n",DefaultNewsgroups); } else { fprintf(tmpfp,"%s\r\n",buffer); } ngmet = 1; } else { if (buffer[0] == '\0') { if (!ngmet && *DefaultNewsgroups) { fprintf(tmpfp,"Newsgroups: %s\r\n",DefaultNewsgroups); } if (!submet) { fprintf(tmpfp,"Subject: (no subject)\r\n"); } if (!pathmet) { fprintf(tmpfp,"Path: from-mail\r\n"); } if (!midmet) { static int seed; time_t now; time(&now); fprintf(tmpfp,"Message-ID: <%d@%d.%d.%d>\r\n",now,getpid(), getuid(), seed); sprintf(mid, "<%d@%d.%d.%d>", now, getpid(), getuid(), seed); seed++; } if (!orgmet && *DefaultOrganization) { fprintf(tmpfp,"Organization: %s\r\n", DefaultOrganization); } if (!approvedmet && *DefaultModerator) { fprintf(tmpfp,"Approved: %s\r\n", DefaultModerator); } } if (strncmp(buffer,"From ",5) != 0 && strncmp(buffer,"To: ",4) !=0) { if (buffer[0] == '\0') { if (*sending_path) { fprintf(tmpfp,"X-Sending-Path: %s\r\n",sending_path); } } fprintf(tmpfp,"%s\r\n",buffer); } } if (buffer[0]=='\0') break; } fprintf(stderr,"Article Body begin ...\n"); pathagain = 0; while (fgets(buffer, sizeof buffer, stdin) != NULL) { char *tmpptr; tmpptr = strchr(buffer,'\n'); if (tmpptr != NULL) *tmpptr = '\0'; if ( headbegin(buffer) ) { FILE *oldfp = bbsnnrp->nnrpin; pathagain = 1; fputs(".\r\n",tmpfp); fclose(tmpfp); fprintf(stderr,"Try to post ...\n"); tmpfp = fopen(tmpfilename,"r"); bbsnnrp->nnrpin = tmpfp; if (!discard) if (INNBBSihave(bbsnnrp, -1, mid)== -1) { fprintf(stderr,"post failed\n"); } bbsnnrp->nnrpin = oldfp; fclose(tmpfp); *mid = '\0'; tmpfp = fopen(tmpfilename,"w"); fprintf(tmpfp,"%s\r\n",buffer); break; } else { fprintf(tmpfp,"%s\r\n",buffer); } } if (!pathagain) break; } if (!pathagain && tmpfp) { FILE *oldfp = bbsnnrp->nnrpin; fputs(".\r\n",tmpfp); fclose(tmpfp); fprintf(stderr,"Try to post ...\n"); tmpfp = fopen(tmpfilename,"r"); bbsnnrp->nnrpin = tmpfp; if (!discard) if (INNBBSihave(bbsnnrp, -1, mid)== -1) { fprintf(stderr,"post failed\n"); } bbsnnrp->nnrpin = oldfp; fclose(tmpfp); } if (isfile(tmpfilename)) { unlink(tmpfilename); } } static char *ACT_BUF, *RC_BUF; int ACT_COUNT; initrcfiles(bbsnnrp) nnrp_t *bbsnnrp; { FILE *actfp, *rcfp; char buff[1024]; int actfd, i, count, actcount=0, rcount=0, maxcount; struct stat st; char *actlistptr, *ptr; actfd = open(bbsnnrp->activefile, O_RDWR); if (actfd < 0) { fprintf( stderr, "can't read/write %s\n", bbsnnrp->activefile ); exit(1); } if (fstat(actfd, &st) != 0) { fprintf( stderr, "can't stat %s\n", bbsnnrp->activefile ); exit(1); } bbsnnrp->actfd = actfd; bbsnnrp->actsize = st.st_size; #ifdef USE_MMAP bbsnnrp->actpointer = mmap(0, st.st_size, PROT_WRITE | PROT_READ, MAP_SHARED, actfd, 0); if (bbsnnrp->actpointer == (char*)-1) { fprintf( stderr, "mmap error \n"); exit(1); } #else if (bbsnnrp->actpointer == NULL) { bbsnnrp->actpointer = (char*)mymalloc(st.st_size); } else { bbsnnrp->actpointer = (char*)myrealloc(bbsnnrp->actpointer,st.st_size); } if (bbsnnrp->actpointer == NULL || read(actfd, bbsnnrp->actpointer, st.st_size) <= 0) { fprintf( stderr, "read act error \n"); exit(1); } #endif bbsnnrp->actend = bbsnnrp->actpointer + st.st_size; i = 0, count = 0; for (ptr = bbsnnrp->actpointer; ptr < bbsnnrp->actend && (actlistptr = (char*)strchr(ptr,'\n')) != NULL; ptr = actlistptr +1, ACT_COUNT++) { if (*ptr == '\n') continue; if (*ptr == '#') continue; count ++; } bbsnnrp->newsrc = (newsrc_t*) mymalloc( sizeof(newsrc_t) * count); ACT_COUNT = 0; for (ptr = bbsnnrp->actpointer; ptr < bbsnnrp->actend && (actlistptr = (char*)strchr(ptr,'\n')) != NULL; ptr = actlistptr +1 ) { register newsrc_t *rcptr; char *nptr; /**actlistptr = '\0';*/ if (*ptr == '\n') continue; if (*ptr == '#') continue; rcptr = &bbsnnrp->newsrc[ACT_COUNT]; rcptr->nameptr = NULL; rcptr->namelen = 0; rcptr->lowptr = NULL; rcptr->lowlen = 0; rcptr->highptr = NULL; rcptr->highlen = 0; rcptr->modeptr = NULL; rcptr->low = 0; rcptr->high = 0; rcptr->mode = 'y'; for (nptr= ptr ;*nptr && isspace(*nptr); ) nptr++; if ( nptr == actlistptr ) continue; rcptr->nameptr = nptr; for (nptr++; *nptr && !isspace(*nptr); ) nptr++; rcptr->namelen = (int)(nptr - rcptr->nameptr); if ( nptr == actlistptr) continue; for (nptr++ ;*nptr && isspace(*nptr); ) nptr++; if ( nptr == actlistptr) continue; rcptr->highptr = nptr; rcptr->high = atol(nptr); for (nptr++; *nptr && !isspace(*nptr); ) nptr++; rcptr->highlen = (int)(nptr - rcptr->highptr); if ( nptr == actlistptr) continue; for (nptr++ ;*nptr && isspace(*nptr); ) nptr++; if ( nptr == actlistptr) continue; rcptr->lowptr = nptr; rcptr->low = atol(nptr); for (nptr++; *nptr && !isspace(*nptr); ) nptr++; rcptr->lowlen = (int)(nptr - rcptr->lowptr); if ( nptr == actlistptr) continue; for (nptr++ ;*nptr && isspace(*nptr); ) nptr++; if ( nptr == actlistptr) continue; rcptr->mode = *nptr; rcptr->modeptr = nptr; ACT_COUNT ++; } } initsockets(server, bbsnnrp, type) char *server; nnrp_t *bbsnnrp; char *type; { int nnrpfd ; int innbbsfd; if (AskLocal) { innbbsfd = unixclient(DefaultPath,"tcp"); if (innbbsfd < 0) { fprintf(stderr, "Connect to %s error. You may not run innbbsd\n", LOCALDAEMON); /* unix connect fail, may run by inetd, try to connect to local once */ innbbsfd = inetclient("localhost",DefaultPort,"tcp"); if (innbbsfd < 0) { exit(2); } close(innbbsfd); /* try again */ innbbsfd = unixclient(DefaultPath,"tcp"); if (innbbsfd < 0) { exit(3); } } verboselog("INNBBS connect to %s\n",DefaultPath); } else { innbbsfd = inetclient(DefaultRemoteHost,DefaultPort,"tcp"); if (innbbsfd < 0) { fprintf(stderr, "Connect to %s at %s error. Remote Server not Ready\n", DefaultRemoteHost, DefaultPort); exit(2); } verboselog("INNBBS connect to %s\n",DefaultRemoteHost); } if (type == StdinInputType) { bbsnnrp->nnrpfd = 0; bbsnnrp->innbbsfd = innbbsfd; if ((bbsnnrp->nnrpin = fdopen(0,"r")) == NULL || (bbsnnrp->nnrpout= fdopen(1,"w")) == NULL || (bbsnnrp->innbbsin= fdopen(innbbsfd,"r")) == NULL || (bbsnnrp->innbbsout= fdopen(innbbsfd,"w"))== NULL ) { fprintf( stderr, "fdopen error\n"); exit(3); } return; } nnrpfd = inetclient(server, "nntp","tcp"); if (nnrpfd < 0) { fprintf(stderr, " connect to %s error \n", server); exit(2); } verboselog("NNRP connect to %s\n", server); bbsnnrp->nnrpfd = nnrpfd; bbsnnrp->innbbsfd = innbbsfd; if ((bbsnnrp->nnrpin = fdopen(nnrpfd,"r")) == NULL || (bbsnnrp->nnrpout= fdopen(nnrpfd,"w")) == NULL || (bbsnnrp->innbbsin= fdopen(innbbsfd,"r")) == NULL || (bbsnnrp->innbbsout= fdopen(innbbsfd,"w"))== NULL ) { fprintf( stderr, "fdopen error\n"); exit(3); } } closesockets() { fclose(BBSNNRP.nnrpin); fclose(BBSNNRP.nnrpout); fclose(BBSNNRP.innbbsin); fclose(BBSNNRP.innbbsout); close(BBSNNRP.nnrpfd); close(BBSNNRP.innbbsfd); } updaterc(actptr, len, value) char *actptr; int len; ULONG value; { for (actptr += len -1; len -- >0; ) { *actptr-- = value % 10 + '0'; value /= 10; } } /* if old file is empty, don't need to update prevent from disk full */ int myrename(old,new) char *old, *new; { struct stat st; if (stat(old,&st) != 0) return -1; if (st.st_size <= 0) return -1; return rename(old,new); } flushrc(bbsnnrp) nnrp_t *bbsnnrp; { int backfd; char *bak1; if (bbsnnrp->actdirty == 0) return; bak1 = (char*)strdup((char*)fileglue("%s.BAK",bbsnnrp->activefile)); if (isfile(bak1)) { myrename(bak1, (char*)fileglue("%s.BAK.OLD",bbsnnrp->activefile)); } #ifdef USE_MMAP if ((backfd=open((char*)fileglue("%s.BAK",bbsnnrp->activefile),O_WRONLY | O_TRUNC | O_CREAT, 0664)) < 0 || write(backfd, bbsnnrp->actpointer, bbsnnrp->actsize) < bbsnnrp->actsize) #else myrename(bbsnnrp->activefile, bak1); if ((backfd=open(bbsnnrp->activefile,O_WRONLY | O_TRUNC | O_CREAT, 0664)) < 0 || write(backfd, bbsnnrp->actpointer, bbsnnrp->actsize) < bbsnnrp->actsize) #endif { char emergent[128]; sprintf(emergent,"/tmp/bbsnnrp.%d.active",getpid()); fprintf(stderr, "write to backup active fail. Maybe disk full\n"); fprintf(stderr, "try to write in %s\n",emergent); if ((backfd = open(emergent,O_WRONLY | O_TRUNC | O_CREAT, 0644))<0 || write(backfd, bbsnnrp->actpointer, bbsnnrp->actsize) < bbsnnrp->actsize) { fprintf(stderr, "write to %sfail.\n", emergent); } else { close(backfd); } /* if write fail, should leave */ /*exit(1);*/ } else { close(backfd); } free(bak1); bbsnnrp->actdirty = 0; } writerc(bbsnnrp) nnrp_t *bbsnnrp; { if (bbsnnrp->actpointer) { flushrc(bbsnnrp); #ifdef USE_MMAP if (munmap(bbsnnrp->actpointer, bbsnnrp->actsize) < 0) fprintf(stderr, "can't unmap\n"); /*free(bbsnnrp->actpointer);*/ bbsnnrp->actpointer = NULL; #endif if (close(bbsnnrp->actfd) < 0) fprintf(stderr, "can't close actfd\n"); } } static FILE* Xhdrfp; static char NNRPbuffer[4096]; static char INNBBSbuffer[4096]; char * NNRPgets(string, len, fp) char *string; int len; FILE *fp; { char* re = fgets(string, len, fp); char *ptr; if (re != NULL) { if ((ptr = (char*)strchr(string,'\r'))!=NULL) *ptr = '\0'; if ((ptr = (char*)strchr(string,'\n'))!=NULL) *ptr = '\0'; } return re; } int NNRPstat(bbsnnrp, artno, mid) nnrp_t *bbsnnrp; ULONG artno; char **mid; { char *ptr; int code; *mid = NULL; fprintf(bbsnnrp->nnrpout,"STAT %d\r\n",artno); fflush(bbsnnrp->nnrpout); verboselog("nnrpPut: STAT %d\n",artno); NNRPgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin); verboselog("nnrpGet: %s\n",NNRPbuffer); ptr = (char*) strchr(NNRPbuffer, ' '); if (ptr != NULL) *ptr++ = '\0'; code = atoi(NNRPbuffer); ptr = (char*) strchr(ptr, ' '); if (ptr != NULL) *ptr++ = '\0'; *mid = ptr; ptr = (char*) strchr(ptr, ' '); if (ptr != NULL) *ptr++ = '\0'; return code; } int NNRPxhdr(pattern, bbsnnrp, i, low, high) char *pattern; nnrp_t *bbsnnrp; int i; ULONG low, high; { newsrc_t *rcptr = &bbsnnrp->newsrc[i]; int size, code; Xhdrfp = bbsnnrp->nnrpin; fprintf(bbsnnrp->nnrpout,"XHDR %s %d-%d\r\n",pattern,low, high ); #ifdef BBSNNRPDEBUG printf("XHDR %s %d-%d\r\n",pattern,low, high ); #endif fflush(bbsnnrp->nnrpout); verboselog("nnrpPut: XHDR %s %d-%d\n",pattern,low, high ); NNRPgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin); verboselog("nnrpGet: %s\n", NNRPbuffer); code = atoi(NNRPbuffer); return code; } int NNRPxhdrget(artno, mid, iscontrol) int *artno; char **mid; int iscontrol; { *mid = NULL; *artno = 0; if (NNRPgets(NNRPbuffer, sizeof NNRPbuffer, Xhdrfp) == NULL) return 0; else { char *ptr, *s; if (strcmp(NNRPbuffer,".")==0) return 0; ptr = (char*)strchr(NNRPbuffer,' '); if (!ptr) return 1; *ptr++ = '\0'; *artno = atol(NNRPbuffer); if (iscontrol) { ptr = (char*)strchr(s=ptr,' '); if (!ptr) return 1; *ptr++ = '\0'; if (strcmp(s,"cancel") != 0) return 1; } *mid = ptr; return 1; } } int INNBBSstat(bbsnnrp, i, mid) nnrp_t *bbsnnrp; int i; char *mid; { newsrc_t *rcptr = &bbsnnrp->newsrc[i]; int size, code; fprintf(bbsnnrp->innbbsout,"STAT %s\r\n", mid); fflush(bbsnnrp->innbbsout); verboselog("innbbsPut: STAT %s\n", mid); NNRPgets(INNBBSbuffer, sizeof INNBBSbuffer, bbsnnrp->innbbsin); verboselog("innbbsGet: %s\n", INNBBSbuffer); return atol(INNBBSbuffer); } int INNBBSihave(bbsnnrp, artno, mid) nnrp_t *bbsnnrp; ULONG artno; char *mid; { int size, code; int header=1; if (DefaultNntpProtocol == NntpPostProtocol) { fprintf(bbsnnrp->innbbsout,"POST\r\n"); fflush(bbsnnrp->innbbsout); verboselog("innbbsPut: POST %s\n", mid); } else { fprintf(bbsnnrp->innbbsout,"IHAVE %s\r\n", mid); fflush(bbsnnrp->innbbsout); verboselog("innbbsPut: IHAVE %s\n", mid); } if (NNRPgets(INNBBSbuffer, sizeof INNBBSbuffer, bbsnnrp->innbbsin)==NULL){ return -1; } verboselog("innbbsGet: %s\n", INNBBSbuffer); #ifdef BBSNNRPDEBUG printf("ihave got %s\n", INNBBSbuffer); #endif if (DefaultNntpProtocol == NntpPostProtocol) { if ((code=atol(INNBBSbuffer)) != NNTP_START_POST_VAL) { if (code == NNTP_POSTFAIL_VAL) return 0; else return -1; } } else { if ((code=atol(INNBBSbuffer)) != INNBBSihaveOK) { if (code == 435 || code == 437) return 0; else return -1; } } if (artno != -1) { fprintf(bbsnnrp->nnrpout,"ARTICLE %d\r\n", artno); verboselog("nnrpPut: ARTICLE %d\n", artno); #ifdef BBSNNRPDEBUG printf("ARTICLE %d\r\n", artno); #endif fflush(bbsnnrp->nnrpout); if (NNRPgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin)==NULL) { return -1; } verboselog("nnrpGet: %s\n", NNRPbuffer); #ifdef BBSNNRPDEBUG printf("article got %s\n", NNRPbuffer); #endif if (atol(NNRPbuffer) != NNRParticleOK) { fputs(".\r\n",bbsnnrp->innbbsout); fflush(bbsnnrp->innbbsout); NNRPgets(INNBBSbuffer, sizeof INNBBSbuffer, bbsnnrp->innbbsin); verboselog("innbbsGet: %s\n",INNBBSbuffer); return 0; } } header = 1; while ( fgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin) != NULL) { if (strcmp(NNRPbuffer,"\r\n") == 0) header = 0; if (strcmp(NNRPbuffer,".\r\n")==0) { verboselog("nnrpGet: .\n"); fputs(NNRPbuffer,bbsnnrp->innbbsout); fflush(bbsnnrp->innbbsout); verboselog("innbbsPut: .\n"); if (NNRPgets(INNBBSbuffer, sizeof INNBBSbuffer, bbsnnrp->innbbsin)==NULL) return -1; verboselog("innbbsGet: %s\n",INNBBSbuffer); #ifdef BBSNNRPDEBUG printf("end ihave got %s\n", INNBBSbuffer); #endif code = atol(INNBBSbuffer); if (DefaultNntpProtocol == NntpPostProtocol) { if (code == NNTP_POSTEDOK_VAL) return 1; if (code == NNTP_POSTFAIL_VAL) return 0; } else { if (code == 235) return 1; if (code == 437 || code == 435) return 0; } break; } if ( DefaultNntpProtocol == NntpPostProtocol && header && strncasecmp(NNRPbuffer,"NNTP-Posting-Host: ",19)==0) { fprintf(bbsnnrp->innbbsout,"X-%s",NNRPbuffer); } else { fputs(NNRPbuffer,bbsnnrp->innbbsout); } } fflush(bbsnnrp->innbbsout); return -1; } int NNRPgroup(bbsnnrp, i, low, high) nnrp_t *bbsnnrp; int i; ULONG *low, *high; { newsrc_t *rcptr = &bbsnnrp->newsrc[i]; int size, code; ULONG tmp; fprintf(bbsnnrp->nnrpout,"GROUP %-.*s\r\n", rcptr->namelen, rcptr->nameptr ); printf("GROUP %-.*s\r\n", rcptr->namelen, rcptr->nameptr ); verboselog("nnrpPut: GROUP %-.*s\n", rcptr->namelen, rcptr->nameptr ); fflush(bbsnnrp->nnrpout); NNRPgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin); verboselog("nnrpGet: %s\n",NNRPbuffer); printf("%s\n",NNRPbuffer); sscanf(NNRPbuffer, "%d %d %ld %ld", &code, &size, low, high); if (*low > *high) { tmp = *low; *low = *high; *high = tmp; } return code; } readnews(server,bbsnnrp) char *server; nnrp_t *bbsnnrp; { int i; char buffer[4096]; ULONG low, high; fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); verboselog("innbbsGet: %s", buffer); if (atoi(buffer) != INNBBSconnectOK) { fprintf(stderr, "INNBBS server not OK\n"); return; } #ifdef BBSNNRPDEBUG printf("%s",buffer); #endif fgets(buffer, sizeof buffer, bbsnnrp->nnrpin); verboselog("nnrpGet: %s", buffer); if (buffer[0] != '2') { /*if (atoi(buffer) != NNRPconnectOK && atoi(buffer) != NNTP_NOPOSTOK_VAL) {*/ fprintf(stderr, "NNRP server not OK\n"); return; } #ifdef BBSNNRPDEBUG printf("%s",buffer); #endif fputs("MODE READER\r\n", bbsnnrp->nnrpout); fflush(bbsnnrp->nnrpout); verboselog("nnrpPut: MODE READER\n"); fgets(buffer, sizeof buffer, bbsnnrp->nnrpin); verboselog("nnrpGet: %s",buffer); if ( DefaultNntpProtocol == NntpPostProtocol ) { fputs("MODE READER\r\n", bbsnnrp->innbbsout); fflush(bbsnnrp->innbbsout); verboselog("innbbsPut: MODE READER\n"); fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); verboselog("innbbsGet: %s",buffer); } #ifdef BBSNNRPDEBUG printf("%s",buffer); #endif if (StatHistory == 0) { fputs("MIDCHECK OFF\r\n", bbsnnrp->innbbsout); fflush(bbsnnrp->innbbsout); verboselog("innbbsPut: MIDCHECK OFF\n"); fgets(buffer, sizeof buffer, bbsnnrp->innbbsin); verboselog("innbbsGet: %s",buffer); } bbsnnrp->actdirty = 0; for (i =0; i< ACT_COUNT; i++) { int code = NNRPgroup(bbsnnrp, i, &low, &high); newsrc_t *rcptr = &bbsnnrp->newsrc[i]; int j; ULONG artno; char *mid; int artcount; #ifdef BBSNNRPDEBUG printf("got reply %d %ld %ld\n",code, low, high); #endif artcount = 0; if (code == 411) { FILE *ff=fopen(BBSHOME"/innd/log/badgroup.log","a"); fprintf(ff,"%s\t%-.*s\r\n", server, rcptr->namelen, rcptr->nameptr); fclose(ff); } else if (code == NNRPGroupOK) { int xcount; ULONG maxartno= rcptr->high; int isCancelControl = (strncmp(rcptr->nameptr,"control",rcptr->namelen)==0) || (strncmp(rcptr->nameptr,"control.cancel",rcptr->namelen)==0) ; /* less than or equal to high, for server renumber */ if (rcptr->low != low) { bbsnnrp->actdirty = 1; rcptr->low = low; updaterc(rcptr->lowptr, rcptr->lowlen, rcptr->low); } if (ResetActive) { if (rcptr->high != high) { bbsnnrp->actdirty = 1; rcptr->high = high; updaterc(rcptr->highptr, rcptr->highlen, rcptr->high); } } else if (rcptr->high < high) { int xhdrcode; ULONG maxget=high; int exception=0; if (rcptr->high < low) { bbsnnrp->actdirty = 1; rcptr->high = low; updaterc(rcptr->highptr, rcptr->highlen, low); } if (high > rcptr->high + Max_Stats) { maxget = rcptr->high + Max_Stats; } if ( isCancelControl ) xhdrcode = NNRPxhdr("Control",bbsnnrp, i, rcptr->high+1, maxget); else xhdrcode = NNRPxhdr("Message-ID",bbsnnrp, i, rcptr->high+1, maxget); maxartno = maxget; if ( xhdrcode == NNRPXhdrOK) { while (NNRPxhdrget(&artno, &mid, isCancelControl)) { /*#define DEBUG*/ #ifdef DEBUG printf("no %d id %s\n",artno, mid); #endif if (artcount < Max_Arts) { if (mid != NULL && !isCancelControl) { if (!StatHistory || INNBBSstat(bbsnnrp,i,mid) != INNBBSstatOK) { printf("** %d ** %d need it %s\n", artcount, artno,mid); XHDR[artcount].artno = artno; XHDR[artcount].header = restrdup(XHDR[artcount].header,mid); /*INNBBSihave(bbsnnrp,i,artno,mid);*/ /* to get it */ artcount++; } } else if (mid != NULL) { if (INNBBSstat(bbsnnrp,i,mid) == INNBBSstatOK) { printf("** %d ** %d need cancel %s\n", artcount, artno,mid); XHDR[artcount].artno = artno; XHDR[artcount].header = restrdup(XHDR[artcount].header,mid); artcount++; } } maxartno = artno; } } }/* while xhdr OK */ exception = 0; for (xcount = 0; xcount < artcount; xcount++) { ULONG artno; char *mid; artno = XHDR[xcount].artno; mid = XHDR[xcount].header; if (isCancelControl) { if (NNRPstat(bbsnnrp,artno,&mid) == NNRPstatOK) { } } printf("** %d ** %d i have it %s\n", xcount, artno, mid); if (!ResetActive && mid != NULL) exception = INNBBSihave(bbsnnrp,artno,mid); if (exception == -1) break; if (rcptr->high != artno) { rcptr->high = artno; updaterc(rcptr->highptr, rcptr->highlen, rcptr->high); } } if (rcptr->high != maxartno && exception != -1) { bbsnnrp->actdirty = 1; rcptr->high = maxartno; updaterc(rcptr->highptr, rcptr->highlen, maxartno); } } } /* flushrc(bbsnnrp); */ } fprintf(bbsnnrp->innbbsout,"quit\r\n"); fprintf(bbsnnrp->nnrpout,"quit\r\n"); fflush(bbsnnrp->innbbsout); fflush(bbsnnrp->nnrpout); fgets(NNRPbuffer, sizeof NNRPbuffer, bbsnnrp->nnrpin); fgets(INNBBSbuffer, sizeof INNBBSbuffer, bbsnnrp->innbbsin); /* bbsnnrp->newsrc[0].high = 1900; updaterc(bbsnnrp->newsrc[0].highptr, bbsnnrp->newsrc[0].highlen, bbsnnrp->newsrc[0].high); */ } INNBBSDhalt() { }