home *** CD-ROM | disk | FTP | other *** search
- /* NEWS.C */
- static char sccsid[] = "@(#)news.c 1.3 94/01/20 (c)1993 thalerd";
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <dirent.h>
- #include <ctype.h>
- #include "config.h"
- #include "struct.h"
- #include "news.h"
- #include "arch.h"
- #include "item.h"
- #include "sep.h"
- #include "range.h"
- #include "sum.h"
- #include "files.h"
- #include "globals.h"
- #include "xalloc.h"
- #include "lib.h"
- #include "stats.h"
- #include "rfp.h" /* for add_response */
-
- #ifdef NEWS
-
- /* So far each item can only have 1 response */
-
- int
- make_rnhead(re,par)
- response_t *re;
- short par;
- {
- FILE *fp,*pp,*sp;
- flag_t ss;
- char buff[MAX_LINE_LENGTH];
- short curr;
- register int cpid,wpid;
- int statusp;
- char *sub;
- char **config;
-
- sub = get_subj(confidx, st_glob.i_current-1, sum);
- if (!(config = get_config(confidx)))
- return 0;
-
- /* Fork & setuid down when creating .rnhead */
- if (cpid=fork()) { /* parent */
- if (cpid<0) return -1; /* error: couldn't fork */
- while ((wpid = wait(&statusp)) != cpid && wpid != -1);
- /* post = !statusp; */
- } else { /* child */
- if (setuid(getuid())) error("setuid","");
- setgid(getgid());
-
- sprintf(buff,"%s/.rnhead",home);
- if (!(fp = mopen(buff,O_W))) exit(1);
- fprintf(fp,"Newsgroups: %s\n",config[CF_NEWSGROUP]);
- fprintf(fp,"Subject: %s%s\n",(sub)?"Re: ":"",
- (sub)? sub : "" );
- fprintf(fp,"Summary: \nExpires: \n");
-
- /* add parents mids:
- fprintf(fp,"References:");
- buff[0]='\0';
- for (curr = par-1; curr>=0; curr = re[curr].parent-1) {
- sprintf(buff2," <%s>%s", message_id(compress(conflist[confidx].name),
- st_glob.i_current,curr,re), buff);
- strcpy(buff,buff2);
- }
- fprintf(fp,"%s\n",buff);
- */
- if (par>0)
- fprintf(fp,"References: <%s>\n", message_id(compress(
- conflist[confidx].name), st_glob.i_current, curr,re));
-
- fprintf(fp,"Sender: \nFollowup-To: \nDistribution: world\n");
- fprintf(fp,"Organization: \nKeywords: \n\n");
- if (par > 0) { /* response to something? */
- pp = st_glob.outp;
- ss = status;
- st_glob.r_current = par-1;
- st_glob.outp = fp;
- status |= S_REDIRECT;
-
- dump_reply("newssep");
-
- st_glob.outp = pp;
- status = ss;
-
- /* dump_reply("newssep"); don't dump to screen */
- }
- sprintf(buff,"%s/.signiture",home);
- if (sp = mopen(buff,O_R)) {
- fprintf(fp,"--\n");
- while (ngets(buff,sp))
- fprintf(fp,"%s\n",buff);
- mclose(sp);
- }
- mclose(fp);
- exit(0);
- }
- return 1;
- }
-
- /******************************************************************************/
- /* NEWS_ITEM_SUM: Incorporate a new article (art) into an item */
- /******************************************************************************/
- int /* RETURNS: 1 on valid, 0 else */
- news_item_sum(art,sum,part,stt,idx) /* ARGUMENTS: */
- long art; /* Article number to incorporate */
- sumentry_t *sum; /* Item summary array to fill in */
- partentry_t *part; /* Participation info */
- short idx; /* Conference index */
- status_t *stt;
- {
- FILE *fp;
- char path[MAX_LINE_LENGTH];
- char buff[MAX_LINE_LENGTH];
- char sj[MAX_LINE_LENGTH], mid[MAX_LINE_LENGTH],
- fromF[MAX_LINE_LENGTH],fromL[MAX_LINE_LENGTH];
- short i;
- sumentry_t this;
- char **config;
-
- /* Load in Subject and Date */
- if (!(config = get_config(idx)))
- return 0;
- sprintf(path,"%s/%s/%ld",NEWSDIR,dot2slash(config[CF_NEWSGROUP]),art);
- if ((fp = mopen(path,O_R))==NULL) return 0;
- do {
- ngets(buff,fp);
- if (!strncmp(buff,"Subject: ",9)) {
- strcpy(sj , buff+9);
- } else if (!strncmp(buff,"Date: ",6)) {
- char *b;
- for (b=buff+6; *b && !isdigit(*b); b++);
- getdate(&(this.last),b);
- this.first = this.last;
- } else if (!strncmp(buff,"From: ",6)) {
- char *p,*q;
-
- if (p = strchr(buff+6,'(')) { /* login (fullname) */
- sscanf(buff+6,"%s",fromL);
- q = strchr(p,')');
- strncpy(fromF,p+1, q-p-1);
- fromF[q-p-1]='\0';
- } else if (p = strchr(buff+6,'<')) { /* fullname <login> */
- strncpy(fromF,buff+6, p-buff-6);
- fromF[p-buff-6]='\0';
- q = strchr(p,'>');
- strncpy(fromL,p+1, q-p-1);
- fromL[q-p-1]='\0';
- } else { /* login */
- strcpy(fromL,buff+6);
- strcpy(fromF,fromL);
- }
- } else if (!strncmp(buff,"Message-ID: <",13)) {
- char *p;
- p = strchr(buff,'>');
- *p='\0';
- strcpy(mid,buff+13);
- }
- } while (strlen(buff)); /* until blank line */
- mclose(fp);
-
- /* Find what item it should go in */
- i=stt->i_last+1;
- /* Duplicate subjects are separate items */
- if (!strncmp(sj,"Re: ",4))
- for (i=stt->i_first;
- i<=stt->i_last && (!sum[i-1].nr
- || (strcmp(sj+4, get_subj(idx,i-1,sum))
- && strcmp(sj, get_subj(idx,i-1,sum))));
- i++);
- /* Duplicate subjects in same item
- for (i=stt->i_first;
- i<=stt->i_last && (!sum[i-1].nr
- || ((strcmp(sj+4, get_subj(idx,i-1,sum)) || strncmp(sj,"Re: ",4))
- && strcmp(sj, get_subj(idx, i-1, sum))));
- i++);
- */
- if (i>stt->i_last) {
- i=stt->i_last+1;
-
- /* Enter a new item */
- /* printf("%d Subject '%s' is new item %d\n",art,sj,i); */
- printf(".");
- this.nr = 1;
- this.flags = IF_ACTIVE;
- do_enter(&this,sj,NULL,idx,sum,part,stt,art,mid,
- uid,fromL,fromF);
- store_subj(idx, i-1, sj);
- } else {
- short resp=0;
-
- /* KKK Find previous reference for parent */
-
- /* Response to item i */
- /* printf("%d Subject '%s' is response to item %d\n",art,sj,i); */
- printf(".");
- stt->i_current = i;
- add_response(&this,NULL,idx,sum,part,stt,art,
- mid,uid,fromL,fromF,resp);
-
- }
- return 1;
- }
-
- void
- news_show_header()
- {
- short pr;
- FILE *fp;
- char buff[MAX_LINE_LENGTH];
- char **config;
-
- open_pipe();
- if (!(config = get_config(confidx)))
- return;
- sprintf(buff,"%s/%s/%d",NEWSDIR,dot2slash(config[CF_NEWSGROUP]),st_glob.i_current);
- if (fp=mopen(buff,O_R)) {
- st_glob.r_current = 0; /* current resp = header */
- get_resp(fp,re,(short)GR_HEADER,(short)0); /* Get header of #0 */
- /* The problem here is that itemsep uses r_current as an index to
- the information in re, so we can't show # new responses
- st_glob.r_current = sum[st_glob.i_current-1].nr
- - abs(part[st_glob.i_current-1].nr);
- */
-
- /* Get info about the actual item text if possible */
- if (re[st_glob.r_current].flags & (RF_EXPIRED|RF_SCRIBBLED))
- pr = 0;
- else if (re[st_glob.r_current].flags & RF_CENSORED)
- pr = ((st_glob.opt_flags & OF_NOFORGET) ||!(flags & O_FORGET));
- else
- pr = 1;
-
- if (pr) get_resp(fp,&(re[st_glob.r_current]),(short)GR_ALL,st_glob.r_current);
- if ((re[st_glob.r_current].flags & RF_SCRIBBLED)
- && re[st_glob.r_current].numchars>7) {
- fseek(fp,re[st_glob.r_current].textoff,0);
- ngets(buff,fp);
- re[st_glob.r_current].text = (char**)buff;
- }
-
- sepinit(IS_CENSORED|IS_UID|IS_DATE);
- itemsep((st_glob.opt_flags & OF_SHORT)?"ishort":"isep",0);
- if (pr) xfree(re[st_glob.r_current].text);
- st_glob.r_current = 0; /* current resp = header */
- mclose(fp);
- }
- }
-
- char *
- message_id(c,i,r,re)
- char *c;
- short i,r;
- response_t *re; /* Response to make id for */
- {
- char str[MAX_LINE_LENGTH];
-
- if (!re[r].mid) {
- sprintf(str,"%d.%d.%X@%s",r,re[r].uid,re[r].date,hostname);
- re[r].mid = xstrdup(str);
- }
- return re[r].mid;
- }
-
- /******************************************************************************/
- /* GET AN ACTUAL ARTICLE */
- /******************************************************************************/
- void /* RETURNS: (nothing) */
- get_article(re) /* ARGUMENTS */
- response_t *re; /* Response to fill in */
- { /* LOCAL VARIABLES: */
- char buff[MAX_LINE_LENGTH];
- char done=0;
- FILE *fp; /* Article file pointer */
- char **config;
-
- re->text = NULL;
- if (!(config = get_config(confidx))) {
- re->flags |= RF_EXPIRED;
- return;
- }
- sprintf(buff,"%s/%s/%d",NEWSDIR,dot2slash(config[CF_NEWSGROUP]),re->article);
- if ((fp=mopen(buff,O_R|O_SILENT))==NULL) {
- re->flags |= RF_EXPIRED;
- /* anything else? */
- return;
- }
-
- /* Get response */
- re->flags = 0;
- if (re->mid) { xfree(re->mid); re->mid = NULL; }
- re->parent = re->article = 0;
-
- while (!done && !(status & S_INT)) {
- if (!ngets(buff,fp)) {
- done=1;
- break;
- }
-
- #if 0
- if (!strncmp(buff,"From: ",6)) {
- char *p,*q;
-
- if (p = strchr(buff+6,'(')) { /* login (fullname) */
- sscanf(buff+6,"%s",n1);
- q = strchr(p,')');
- strncpy(n2,p+1, q-p-1);
- n2[q-p-1]='\0';
- } else if (p = strchr(buff+6,'<')) { /* fullname <login> */
- strncpy(n2,buff+6, p-buff-6);
- n2[p-buff-6]='\0';
- q = strchr(p,'>');
- strncpy(n1,p+1, q-p-1);
- n1[q-p-1]='\0';
- } else { /* login */
- strcpy(n1,buff+6);
- strcpy(n2,n1);
- }
-
- re->uid = 0;
- if (re->login) xfree(re->login);
- re->login = xstrdup(n1);
- if (re->fullname) xfree(re->fullname);
- re->fullname=xstrdup(n2);
- } else if (!strncmp(buff,"Date: ",6)) {
- getdate(&(re->date),buff+11);
- } else
- #endif
- if (!strncmp(buff,"Message-ID: <",13)) {
- char *p;
- p = strchr(buff,'>');
- *p='\0';
- re->mid = xstrdup(buff+13);
- } else if (!strlen(buff)) {
- long textoff;
-
- textoff = ftell(fp);
- re->text = grab_more(fp,(flags & O_SIGNITURE)?NULL:"--",0);
- re->numchars= ftell(fp) - textoff;
- done=1;
- break;
- }
- }
- mclose(fp);
- }
-
- /******************************************************************************/
- /* DOT2SLASH: Return directory/string/form of news.group.string passed in */
- /******************************************************************************/
- char * /* RETURNS: Slash-separated string */
- dot2slash(str) /* ARGUMENTS: */
- char *str; /* Dot-separated string */
- {
- static char buff[MAX_LINE_LENGTH];
- char *f,*t;
-
- for (f=str,t=buff; *f; f++,t++) {
- *t = (*f == '.')? '/' : *f;
- }
- *t = '\0';
- return buff;
- }
-
- /******************************************************************************/
- /* REFRESH_NEWS: Look for any new articles, and if any are found, incorporate */
- /* them into item files */
- /******************************************************************************/
- void /* RETURNS: (nothing) */
- refresh_news(sum,part,stt,idx) /* ARGUMENTS: */
- sumentry_t *sum; /* Summary array to update */
- partentry_t *part; /* Participation info */
- short idx; /* Conference index to update */
- status_t *stt; /* Status info to update */
- {
- char path[MAX_LINE_LENGTH],
- artpath[MAX_LINE_LENGTH],
- fmt[MAX_LINE_LENGTH];
- struct stat st;
- char **config;
- long article;
- DIR *fp;
- FILE *artp;
- struct dirent *dp;
- int i;
-
- strcpy(fmt,"%d");
- if (!(config = get_config(idx)))
- return;
-
- sprintf(path,"%s/%s",NEWSDIR,dot2slash(config[CF_NEWSGROUP]));
- if (stat(path,&st)) {
- error("refreshing ",path);
- return;
- }
-
- /* Is there new stuff? */
- if (st.st_mtime!=stt->sumtime) {
- long mod;
- struct stat artst;
-
- sprintf(artpath,"%s/article",conflist[idx].location);
-
- /* Create if doesn't exist, else update */
- if (stat(artpath,&artst)) mod = O_W;
- else mod = O_RPLUS;
-
- /* if (stt->c_security & CT_BASIC) mod |= O_PRIVATE;*/
- if ((artp=mopen(path, mod))==NULL) return; /* can't lock */
-
- if ((fp = opendir(path))==NULL) {
- error("opening ",path);
- return;
- }
- refresh_stats(sum,part,stt); /* update stt */
-
- /* Load in stats 1 piece at a time - the slow stuff */
- article = stt->c_article;
- for (dp = readdir(fp); dp != NULL && !(status & S_INT); dp=readdir(fp)) {
- long i2;
- if (sscanf(dp->d_name,fmt,&i2)==1 && i2>stt->c_article) {
- news_item_sum(i2,sum,part,stt,idx);
- if (i2>article) {
- article=i2;
- fseek(artp, 0L, 0);
- fprintf(artp,"%ld\n",article);
- }
- refresh_stats(sum,part,stt); /* update stt */
- }
- }
- closedir(fp);
-
- /* Check for expired */
- for (i=stt->i_first; i<=stt->i_last; i++) {
- response_t re;
- FILE *fp2;
- char buff[MAX_LINE_LENGTH];
-
- sprintf(buff,"%s/_%d",conflist[idx].location,i);
- if (fp2=mopen(buff,O_R)) {
- re.fullname = re.login = re.mid = 0;
- re.text = 0;
- re.offset = -1;
-
- get_resp(fp2, &re, GR_ALL, 0);
- if (re.flags & RF_EXPIRED)
- sum[i-1].flags |= IF_EXPIRED;
- mclose(fp2);
-
- if (re.fullname) xfree(re.fullname);
- if (re.login) xfree(re.login);
- if (re.text) xfree(re.text);
- if (re.mid) xfree(re.mid);
- }
- }
-
- stt->sumtime = st.st_mtime;
- stt->c_article = article;
- refresh_stats(sum,part,stt); /* update stt */
- save_sum(sum,0,idx,stt);
-
- mclose(artp); /* release lock on article file */
- }
- }
- #endif
-