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

  1. /* NEWS.C */
  2. static   char sccsid[] = "@(#)news.c 1.3 94/01/20 (c)1993 thalerd";
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <dirent.h>
  8. #include <ctype.h>
  9. #include "config.h"
  10. #include "struct.h"
  11. #include "news.h"
  12. #include "arch.h"
  13. #include "item.h"
  14. #include "sep.h"
  15. #include "range.h"
  16. #include "sum.h"
  17. #include "files.h"
  18. #include "globals.h"
  19. #include "xalloc.h"
  20. #include "lib.h"
  21. #include "stats.h"
  22. #include "rfp.h"   /* for add_response */
  23.  
  24. #ifdef NEWS
  25.  
  26. /* So far each item can only have 1 response */
  27.  
  28. int
  29. make_rnhead(re,par)
  30. response_t *re;
  31. short par;
  32. {
  33.    FILE *fp,*pp,*sp;
  34.    flag_t ss;
  35.    char buff[MAX_LINE_LENGTH];
  36.    short curr;
  37.    register int cpid,wpid;
  38.    int statusp;
  39.    char *sub;
  40.    char **config;
  41.  
  42.    sub = get_subj(confidx, st_glob.i_current-1, sum);
  43.    if (!(config = get_config(confidx)))
  44.       return 0;
  45.  
  46.    /* Fork & setuid down when creating .rnhead */
  47.    if (cpid=fork()) { /* parent */
  48.       if (cpid<0) return -1; /* error: couldn't fork */
  49.       while ((wpid = wait(&statusp)) != cpid && wpid != -1);
  50.       /* post = !statusp; */
  51.    } else { /* child */
  52.       if (setuid(getuid())) error("setuid","");
  53.       setgid(getgid());
  54.  
  55.       sprintf(buff,"%s/.rnhead",home);
  56.       if (!(fp = mopen(buff,O_W))) exit(1);
  57.       fprintf(fp,"Newsgroups: %s\n",config[CF_NEWSGROUP]);
  58.       fprintf(fp,"Subject: %s%s\n",(sub)?"Re: ":"", 
  59.        (sub)? sub : "" );
  60.       fprintf(fp,"Summary: \nExpires: \n");
  61.    
  62.       /* add parents mids:
  63.       fprintf(fp,"References:"); 
  64.       buff[0]='\0';
  65.       for (curr = par-1; curr>=0; curr = re[curr].parent-1) {
  66.          sprintf(buff2," <%s>%s", message_id(compress(conflist[confidx].name),
  67.              st_glob.i_current,curr,re), buff); 
  68.          strcpy(buff,buff2);   
  69.       }
  70.       fprintf(fp,"%s\n",buff);
  71.       */
  72.       if (par>0)
  73.          fprintf(fp,"References: <%s>\n", message_id(compress(
  74.      conflist[confidx].name), st_glob.i_current, curr,re));
  75.  
  76.       fprintf(fp,"Sender: \nFollowup-To: \nDistribution: world\n");
  77.       fprintf(fp,"Organization: \nKeywords: \n\n");
  78.       if (par > 0) { /* response to something? */
  79.          pp = st_glob.outp;
  80.          ss = status;
  81.          st_glob.r_current = par-1;
  82.          st_glob.outp = fp;
  83.          status |= S_REDIRECT;
  84.    
  85.          dump_reply("newssep");
  86.    
  87.          st_glob.outp = pp;
  88.          status     = ss;
  89.    
  90.          /* dump_reply("newssep"); don't dump to screen */
  91.       }
  92.       sprintf(buff,"%s/.signiture",home);
  93.       if (sp = mopen(buff,O_R)) {
  94.          fprintf(fp,"--\n");
  95.          while (ngets(buff,sp))
  96.        fprintf(fp,"%s\n",buff);
  97.          mclose(sp);
  98.       }
  99.       mclose(fp);
  100.       exit(0);
  101.    }
  102.    return 1;
  103. }
  104.  
  105. /******************************************************************************/
  106. /* NEWS_ITEM_SUM: Incorporate a new article (art) into an item                */
  107. /******************************************************************************/
  108. int                    /* RETURNS: 1 on valid, 0 else      */
  109. news_item_sum(art,sum,part,stt,idx) /* ARGUMENTS: */
  110. long         art;      /*    Article number to incorporate */
  111. sumentry_t  *sum;      /*    Item summary array to fill in */
  112. partentry_t *part;     /*    Participation info            */
  113. short        idx;      /*    Conference index              */
  114. status_t    *stt;
  115. {
  116.    FILE       *fp;
  117.    char        path[MAX_LINE_LENGTH];
  118.    char        buff[MAX_LINE_LENGTH];
  119.    char        sj[MAX_LINE_LENGTH], mid[MAX_LINE_LENGTH],
  120.                fromF[MAX_LINE_LENGTH],fromL[MAX_LINE_LENGTH];
  121.    short       i;
  122.    sumentry_t  this;
  123.    char      **config;
  124.  
  125.    /* Load in Subject and Date */
  126.    if (!(config = get_config(idx)))
  127.       return 0;
  128.    sprintf(path,"%s/%s/%ld",NEWSDIR,dot2slash(config[CF_NEWSGROUP]),art);
  129.    if ((fp = mopen(path,O_R))==NULL) return 0;
  130.    do {
  131.       ngets(buff,fp); 
  132.       if (!strncmp(buff,"Subject: ",9)) {
  133.          strcpy(sj , buff+9);
  134.       } else if (!strncmp(buff,"Date: ",6)) {
  135.     char *b;
  136.     for (b=buff+6; *b && !isdigit(*b); b++);
  137.     getdate(&(this.last),b);
  138.     this.first = this.last;
  139.       } else if (!strncmp(buff,"From: ",6)) {
  140.             char *p,*q;
  141.  
  142.             if (p = strchr(buff+6,'(')) { /* login (fullname) */
  143.                sscanf(buff+6,"%s",fromL);
  144.                q = strchr(p,')');
  145.                strncpy(fromF,p+1, q-p-1);
  146.                fromF[q-p-1]='\0';
  147.        } else if (p = strchr(buff+6,'<')) { /* fullname <login> */
  148.                strncpy(fromF,buff+6, p-buff-6);
  149.                fromF[p-buff-6]='\0';
  150.                q = strchr(p,'>');
  151.                strncpy(fromL,p+1, q-p-1);
  152.                fromL[q-p-1]='\0';
  153.        } else { /* login */
  154.                strcpy(fromL,buff+6);
  155.                strcpy(fromF,fromL);
  156.        }
  157.       } else if (!strncmp(buff,"Message-ID: <",13)) {
  158.        char *p;
  159.          p = strchr(buff,'>');
  160.        *p='\0';
  161.        strcpy(mid,buff+13);
  162.       }
  163.    } while (strlen(buff)); /* until blank line */
  164.    mclose(fp);
  165.  
  166.    /* Find what item it should go in */
  167.    i=stt->i_last+1;
  168. /* Duplicate subjects are separate items */
  169.    if (!strncmp(sj,"Re: ",4)) 
  170.       for (i=stt->i_first; 
  171.            i<=stt->i_last && (!sum[i-1].nr 
  172.           || (strcmp(sj+4, get_subj(idx,i-1,sum)) 
  173.            && strcmp(sj,   get_subj(idx,i-1,sum)))); 
  174.          i++);
  175. /* Duplicate subjects in same item 
  176.    for (i=stt->i_first; 
  177.         i<=stt->i_last && (!sum[i-1].nr 
  178.     || ((strcmp(sj+4, get_subj(idx,i-1,sum)) || strncmp(sj,"Re: ",4)) 
  179.      && strcmp(sj, get_subj(idx, i-1, sum)))); 
  180.    i++);
  181.  */
  182.    if (i>stt->i_last) {
  183.       i=stt->i_last+1;
  184.  
  185.       /* Enter a new item */
  186. /* printf("%d Subject '%s' is new item %d\n",art,sj,i); */
  187.         printf(".");
  188.       this.nr = 1;
  189.       this.flags = IF_ACTIVE;
  190.       do_enter(&this,sj,NULL,idx,sum,part,stt,art,mid,
  191.        uid,fromL,fromF);
  192.       store_subj(idx, i-1, sj);
  193.    } else {
  194.       short resp=0;
  195.  
  196.       /* KKK Find previous reference for parent */
  197.  
  198.       /* Response to item i */
  199. /* printf("%d Subject '%s' is response to item %d\n",art,sj,i); */
  200.         printf(".");
  201.       stt->i_current = i;
  202.       add_response(&this,NULL,idx,sum,part,stt,art,
  203.        mid,uid,fromL,fromF,resp);
  204.  
  205.    }
  206.    return 1;
  207. }
  208.  
  209. void
  210. news_show_header()
  211. {
  212.    short pr;
  213.    FILE *fp;
  214.    char  buff[MAX_LINE_LENGTH];
  215.    char **config;
  216.  
  217.    open_pipe();
  218.    if (!(config = get_config(confidx)))
  219.       return;
  220.    sprintf(buff,"%s/%s/%d",NEWSDIR,dot2slash(config[CF_NEWSGROUP]),st_glob.i_current);
  221.    if (fp=mopen(buff,O_R)) {
  222.       st_glob.r_current = 0; /* current resp = header */
  223.       get_resp(fp,re,(short)GR_HEADER,(short)0); /* Get header of #0 */
  224. /* The problem here is that itemsep uses r_current as an index to
  225.    the information in re, so we can't show # new responses
  226.       st_glob.r_current = sum[st_glob.i_current-1].nr
  227.        - abs(part[st_glob.i_current-1].nr);
  228.  */
  229.  
  230.       /* Get info about the actual item text if possible */
  231.       if (re[st_glob.r_current].flags & (RF_EXPIRED|RF_SCRIBBLED))
  232.     pr = 0;
  233.       else if (re[st_glob.r_current].flags & RF_CENSORED)
  234.          pr = ((st_glob.opt_flags & OF_NOFORGET) ||!(flags & O_FORGET));
  235.       else
  236.      pr = 1;
  237.  
  238.       if (pr) get_resp(fp,&(re[st_glob.r_current]),(short)GR_ALL,st_glob.r_current);
  239.       if ((re[st_glob.r_current].flags & RF_SCRIBBLED)
  240.        && re[st_glob.r_current].numchars>7) {
  241.          fseek(fp,re[st_glob.r_current].textoff,0);
  242.          ngets(buff,fp);
  243.          re[st_glob.r_current].text = (char**)buff;
  244.       }
  245.  
  246.       sepinit(IS_CENSORED|IS_UID|IS_DATE);
  247.       itemsep((st_glob.opt_flags & OF_SHORT)?"ishort":"isep",0);
  248.       if (pr) xfree(re[st_glob.r_current].text);
  249.       st_glob.r_current = 0; /* current resp = header */
  250.       mclose(fp);
  251.    }
  252. }
  253.  
  254. char *
  255. message_id(c,i,r,re)
  256. char       *c;
  257. short       i,r;
  258. response_t *re;      /*    Response to make id for     */
  259. {
  260.    char str[MAX_LINE_LENGTH];
  261.  
  262.    if (!re[r].mid) {
  263.       sprintf(str,"%d.%d.%X@%s",r,re[r].uid,re[r].date,hostname);
  264.       re[r].mid = xstrdup(str);
  265.    }
  266.    return re[r].mid;
  267. }
  268.  
  269. /******************************************************************************/
  270. /* GET AN ACTUAL ARTICLE                                                      */
  271. /******************************************************************************/
  272. void                     /* RETURNS: (nothing)             */
  273. get_article(re)      /* ARGUMENTS                      */
  274. response_t *re;          /*    Response to fill in         */
  275. {                        /* LOCAL VARIABLES:               */
  276.    char       buff[MAX_LINE_LENGTH];
  277.    char       done=0;
  278.    FILE      *fp;        /*    Article file pointer        */
  279.    char     **config;
  280.  
  281.    re->text = NULL;
  282.    if (!(config = get_config(confidx))) {
  283.       re->flags  |= RF_EXPIRED;
  284.       return;
  285.    }
  286.    sprintf(buff,"%s/%s/%d",NEWSDIR,dot2slash(config[CF_NEWSGROUP]),re->article);
  287.    if ((fp=mopen(buff,O_R|O_SILENT))==NULL) {
  288.       re->flags  |= RF_EXPIRED;
  289.       /* anything else? */
  290.       return;
  291.    }
  292.  
  293.    /* Get response */
  294.    re->flags   = 0;
  295.    if (re->mid) { xfree(re->mid); re->mid = NULL; }
  296.    re->parent = re->article = 0;
  297.  
  298.    while (!done && !(status & S_INT)) {
  299.       if (!ngets(buff,fp)) {
  300.          done=1; 
  301.          break; 
  302.       }
  303.  
  304. #if 0
  305.       if (!strncmp(buff,"From: ",6)) {
  306.          char *p,*q;
  307.  
  308.          if (p = strchr(buff+6,'(')) { /* login (fullname) */
  309.             sscanf(buff+6,"%s",n1);
  310.             q = strchr(p,')');
  311.             strncpy(n2,p+1, q-p-1);
  312.             n2[q-p-1]='\0';
  313.     } else if (p = strchr(buff+6,'<')) { /* fullname <login> */
  314.             strncpy(n2,buff+6, p-buff-6);
  315.             n2[p-buff-6]='\0';
  316.             q = strchr(p,'>');
  317.             strncpy(n1,p+1, q-p-1);
  318.             n1[q-p-1]='\0';
  319.     } else { /* login */
  320.             strcpy(n1,buff+6);
  321.             strcpy(n2,n1);
  322.     }
  323.  
  324.          re->uid = 0;
  325.          if (re->login) xfree(re->login);
  326.          re->login = xstrdup(n1);
  327.          if (re->fullname) xfree(re->fullname);
  328.          re->fullname=xstrdup(n2);
  329.       } else if (!strncmp(buff,"Date: ",6)) {
  330.          getdate(&(re->date),buff+11);
  331.       } else 
  332. #endif
  333.       if (!strncmp(buff,"Message-ID: <",13)) {
  334.        char *p;
  335.          p = strchr(buff,'>');
  336.        *p='\0';
  337.        re->mid = xstrdup(buff+13);
  338.       } else if (!strlen(buff)) {
  339.      long textoff;
  340.  
  341.           textoff = ftell(fp); 
  342.           re->text = grab_more(fp,(flags & O_SIGNITURE)?NULL:"--",0);
  343.           re->numchars= ftell(fp) - textoff;
  344.           done=1;
  345.           break;
  346.       }
  347.    }
  348.    mclose(fp);
  349. }
  350.  
  351. /******************************************************************************/
  352. /* DOT2SLASH: Return directory/string/form of news.group.string passed in     */
  353. /******************************************************************************/
  354. char *         /* RETURNS: Slash-separated string */
  355. dot2slash(str) /* ARGUMENTS:                      */
  356. char *str;     /*    Dot-separated string         */
  357. {
  358. static char buff[MAX_LINE_LENGTH];
  359.        char *f,*t;
  360.  
  361.    for (f=str,t=buff; *f; f++,t++) {
  362.       *t = (*f == '.')? '/' : *f;
  363.    }
  364.    *t = '\0';
  365.    return buff;
  366. }
  367.  
  368. /******************************************************************************/
  369. /* REFRESH_NEWS: Look for any new articles, and if any are found, incorporate */
  370. /* them into item files                                                       */
  371. /******************************************************************************/
  372. void                                     /* RETURNS: (nothing)             */
  373. refresh_news(sum,part,stt,idx) /* ARGUMENTS:                     */
  374. sumentry_t  *sum;                        /*    Summary array to update     */
  375. partentry_t *part;                       /*    Participation info          */
  376. short        idx;                        /*    Conference index to update  */
  377. status_t    *stt;                        /*    Status info to update       */
  378. {
  379.    char           path[MAX_LINE_LENGTH],
  380.                   artpath[MAX_LINE_LENGTH],
  381.                   fmt[MAX_LINE_LENGTH];
  382.    struct stat    st;
  383.    char         **config;
  384.    long           article;
  385.    DIR           *fp;
  386.     FILE          *artp;
  387.    struct dirent *dp;
  388.    int            i;
  389.  
  390.    strcpy(fmt,"%d");
  391.    if (!(config = get_config(idx)))
  392.       return;
  393.  
  394.    sprintf(path,"%s/%s",NEWSDIR,dot2slash(config[CF_NEWSGROUP]));
  395.    if (stat(path,&st)) {
  396.       error("refreshing ",path);
  397.       return;
  398.    }
  399.  
  400.    /* Is there new stuff? */
  401.    if (st.st_mtime!=stt->sumtime) {
  402.       long mod;
  403.       struct stat artst;
  404.  
  405.       sprintf(artpath,"%s/article",conflist[idx].location);
  406.  
  407.       /* Create if doesn't exist, else update */
  408.       if (stat(artpath,&artst)) mod = O_W;
  409.       else                      mod = O_RPLUS;
  410.  
  411.       /* if (stt->c_security & CT_BASIC) mod |= O_PRIVATE;*/
  412.       if ((artp=mopen(path, mod))==NULL) return;  /* can't lock */
  413.  
  414.       if ((fp = opendir(path))==NULL) {
  415.          error("opening ",path);
  416.          return;
  417.       }
  418.       refresh_stats(sum,part,stt); /* update stt */
  419.      
  420.       /* Load in stats 1 piece at a time - the slow stuff */
  421.       article = stt->c_article;
  422.       for (dp = readdir(fp); dp != NULL && !(status & S_INT); dp=readdir(fp)) {
  423.          long i2;
  424.          if (sscanf(dp->d_name,fmt,&i2)==1 && i2>stt->c_article) {
  425.             news_item_sum(i2,sum,part,stt,idx);
  426.             if (i2>article) {
  427.                article=i2;
  428.                     fseek(artp, 0L, 0);
  429.                fprintf(artp,"%ld\n",article);
  430.             }
  431.             refresh_stats(sum,part,stt); /* update stt */
  432.          }
  433.       }
  434.       closedir(fp);
  435.  
  436.       /* Check for expired */
  437.       for (i=stt->i_first; i<=stt->i_last; i++) {
  438.          response_t re;
  439.          FILE *fp2;
  440.          char buff[MAX_LINE_LENGTH];
  441.  
  442.          sprintf(buff,"%s/_%d",conflist[idx].location,i);
  443.          if (fp2=mopen(buff,O_R)) {
  444.             re.fullname = re.login = re.mid = 0;
  445.             re.text = 0;
  446.             re.offset = -1;
  447.  
  448.             get_resp(fp2, &re, GR_ALL, 0);
  449.             if (re.flags & RF_EXPIRED)
  450.                sum[i-1].flags |= IF_EXPIRED;
  451.             mclose(fp2);
  452.  
  453.             if (re.fullname) xfree(re.fullname);
  454.             if (re.login)    xfree(re.login);
  455.             if (re.text)     xfree(re.text);
  456.             if (re.mid)      xfree(re.mid);
  457.          }
  458.       }
  459.  
  460.       stt->sumtime   = st.st_mtime; 
  461.       stt->c_article = article;
  462.       refresh_stats(sum,part,stt); /* update stt */
  463.       save_sum(sum,0,idx,stt);
  464.  
  465.       mclose(artp); /* release lock on article file */
  466.    }
  467. }
  468. #endif
  469.