home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume28
/
yapp
/
part03
/
news.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-29
|
14KB
|
469 lines
/* 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