home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume27 / trn-3.3 / part04 / kfile.c < prev    next >
C/C++ Source or Header  |  1993-11-27  |  11KB  |  505 lines

  1. /* $Id: kfile.c,v 3.0 1991/09/09 20:18:23 davison Trn $
  2.  */
  3. /* This software is Copyright 1991 by Stan Barber. 
  4.  *
  5.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  6.  * use this software as long as: there is no monetary profit gained
  7.  * specifically from the use or reproduction of this software, it is not
  8.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  9.  * included prominently in any copy made. 
  10.  *
  11.  * The authors make no claims as to the fitness or correctness of this software
  12.  * for any use whatsoever, and it is provided as is. Any use of this software
  13.  * is at the user's own risk. 
  14.  */
  15.  
  16. #include "EXTERN.h"
  17. #include "common.h"
  18. #include "term.h"
  19. #include "util.h"
  20. #include "cache.h"
  21. #include "artsrch.h"
  22. #include "ng.h"
  23. #include "ngdata.h"
  24. #include "intrp.h"
  25. #include "ngstuff.h"
  26. #include "rcstuff.h"
  27. #include "trn.h"
  28. #include "hash.h"
  29. #include "rthread.h"
  30. #include "rt-process.h"
  31. #include "rt-select.h"
  32. #include "INTERN.h"
  33. #include "kfile.h"
  34.  
  35. extern HASHTABLE *msgid_hash;
  36.  
  37. static bool exitcmds = FALSE;
  38.  
  39. void
  40. kfile_init()
  41. {
  42.     ;
  43. }
  44.  
  45. #ifndef KILLFILES
  46. int
  47. edit_kfile()
  48. {
  49.     notincl("^K");
  50.     return -1;
  51. }
  52.  
  53. #else /* KILLFILES */
  54.  
  55. char killglobal[] = KILLGLOBAL;
  56. char killlocal[] = KILLLOCAL;
  57.  
  58. void
  59. mention(str)
  60. char *str;
  61. {
  62. #ifdef VERBOSE
  63.     IF(verbose) {
  64. #ifdef NOFIREWORKS
  65.     no_sofire();
  66. #endif
  67.     standout();
  68.     fputs(str,stdout);
  69.     un_standout();
  70.     putchar('\n');
  71.     }
  72.     ELSE
  73. #endif
  74. #ifdef TERSE
  75.     putchar('.');
  76. #endif
  77.     fflush(stdout);
  78. }
  79.  
  80. static bool kill_mentioned;
  81.  
  82. int
  83. do_kfile(kfp,entering)
  84. FILE *kfp;
  85. int entering;
  86. {
  87.     bool first_time = (entering && !killfirst);
  88.     ART_UNREAD selections = selected_count;
  89.     ART_UNREAD unread = toread[ng];
  90.     int thread_kill_cnt = 0;
  91.     int thread_select_cnt = 0;
  92.     char *cp;
  93.  
  94.     art = lastart+1;
  95.     killfirst = firstart;
  96.     fseek(kfp,0L,0);            /* rewind file */
  97.     while (fgets(buf,LBUFLEN,kfp) != Nullch) {
  98.     if (*(cp = buf + strlen(buf) - 1) == '\n')
  99.         *cp = '\0';
  100.     if (strnEQ(buf,"THRU",4)) {
  101.         killfirst = atol(buf+4)+1;
  102.         if (killfirst < absfirst)
  103.         killfirst = absfirst;
  104.         if (killfirst > lastart)
  105.         killfirst = lastart+1;
  106.         if (entering)
  107.         localkf_changes |= 1;
  108.         continue;
  109.     }
  110.     if (*buf == 'X') {        /* exit command? */
  111.         if (entering) {
  112.         exitcmds = TRUE;
  113.         continue;
  114.         }
  115.         strcpy(buf,buf+1);
  116.     }
  117.     else if (!entering)
  118.         continue;
  119.  
  120.     if (*buf == '&') {
  121.         mention(buf);
  122.         switcheroo();
  123.     }
  124.     else if (*buf == '/') {
  125.         has_normal_kills = TRUE;
  126.         if (firstart > lastart)
  127.         continue;
  128.         mention(buf);
  129.         kill_mentioned = TRUE;
  130.         switch (art_search(buf, (sizeof buf), FALSE)) {
  131.         case SRCH_ABORT:
  132.         continue;
  133.         case SRCH_INTR:
  134. #ifdef VERBOSE
  135.         IF(verbose)
  136.             printf("\n(Interrupted at article %ld)\n",(long)art)
  137.               FLUSH;
  138.         ELSE
  139. #endif
  140. #ifdef TERSE
  141.             printf("\n(Intr at %ld)\n",(long)art) FLUSH;
  142. #endif
  143.         return -1;
  144.         case SRCH_DONE:
  145.         break;
  146.         case SRCH_SUBJDONE:
  147.         fputs("\tsubject not found (?)\n",stdout) FLUSH;
  148.         break;
  149.         case SRCH_NOTFOUND:
  150.         fputs("\tnot found\n",stdout) FLUSH;
  151.         break;
  152.         case SRCH_FOUND:
  153.         fputs("\tfound\n",stdout) FLUSH;
  154.         }
  155.     }
  156.     else if (first_time && *buf == '<') {
  157.         register ARTICLE *ap;
  158.         cp = index(buf,' ');
  159.         if (!cp)
  160.         cp = "T,";
  161.         else
  162.         *cp++ = '\0';
  163.         if ((ap = get_article(buf)) != Nullart) {
  164.         if ((ap->flags & AF_FAKE) == AF_FAKE) {
  165.             if (*cp == 'T')
  166.             cp++;
  167.             switch (*cp) {
  168.             case '+':
  169.             ap->flags |= AF_AUTOSELECTALL;
  170.             thread_select_cnt++;
  171.             break;
  172.             case '.':
  173.             ap->flags |= AF_AUTOSELECT;
  174.             thread_select_cnt++;
  175.             break;
  176.             case 'J':
  177.             case 'j':
  178.             ap->flags |= AF_AUTOKILLALL;
  179.             thread_kill_cnt++;
  180.             break;
  181.             case ',':
  182.             ap->flags |= AF_AUTOKILL;
  183.             thread_kill_cnt++;
  184.             break;
  185.             }
  186.         } else {
  187.             art = article_num(ap);
  188.             artp = ap;
  189.             perform(cp,FALSE);
  190.             if (ap->flags & (AF_AUTOSELECT|AF_AUTOSELECTALL))
  191.             thread_select_cnt++;
  192.             else if (ap->flags & (AF_AUTOKILL|AF_AUTOKILLALL))
  193.             thread_kill_cnt++;
  194.         }
  195.         }
  196.         art = lastart+1;
  197.     } else if (*buf == '*') {
  198.         register ARTICLE *ap;
  199.         register int killmask = AF_READ;
  200.         switch (buf[1]) {
  201.         case 'X':
  202.         killmask |= sel_mask;    /* don't kill selected articles */
  203.         /* FALL THROUGH */
  204.         case 'j':
  205.         for (art = killfirst, ap = article_ptr(killfirst);
  206.              art <= lastart;
  207.              art++, ap++
  208.         ) {
  209.             if (!(ap->flags & killmask))
  210.             set_read(ap);
  211.         }
  212.         break;
  213.         }
  214.         has_normal_kills = TRUE;
  215.     }
  216.     }
  217.     if (thread_kill_cnt) {
  218.     sprintf(buf,"%ld auto-kill command%s.", (long)thread_kill_cnt,
  219.         thread_kill_cnt == 1? "" : "s");
  220.     mention(buf);
  221.     kill_mentioned = TRUE;
  222.     }
  223.     if (thread_select_cnt) {
  224.     sprintf(buf,"%ld auto-select command%s.", (long)thread_select_cnt,
  225.         thread_select_cnt == 1? "" : "s");
  226.     mention(buf);
  227.     kill_mentioned = TRUE;
  228.     }
  229.     unread -= toread[ng];
  230.     selections -= selected_count;
  231. #ifdef VERBOSE
  232.     IF(verbose && (unread > 0 || selections < 0)) {
  233.     putchar('\n');
  234.     if (unread > 0) {
  235.         printf("Killed %ld article%s", (long)unread,
  236.         unread == 1? nullstr : "s");
  237.         if (selections < 0)
  238.         fputs("; ",stdout);
  239.     }
  240.     if (selections < 0)
  241.         printf("Selected %ld article%s", (long)-selections,
  242.         selections == -1? nullstr : "s");
  243.     fputs(".\n",stdout) FLUSH;
  244.     kill_mentioned = TRUE;
  245.     }
  246. #endif
  247.     return 0;
  248. }
  249.  
  250. void
  251. kill_unwanted(starting,message,entering)
  252. ART_NUM starting;
  253. char *message;
  254. int entering;
  255. {
  256.     bool intr = FALSE;            /* did we get an interrupt? */
  257.     ART_NUM oldfirst;
  258.     char oldmode = mode;
  259.     bool anytokill = (toread[ng] > 0);
  260.  
  261.     mode = 'k';
  262.     if ((entering || exitcmds) && (localkfp || globkfp)) {
  263.     exitcmds = FALSE;
  264.     oldfirst = firstart;
  265.     firstart = starting;
  266.     clear();
  267. #ifdef VERBOSE
  268. # ifdef TERSE
  269.     if (message && (verbose || entering))
  270. # else
  271.     if (message)
  272. # endif
  273. #else
  274.     if (message && entering)
  275. #endif
  276.         fputs(message,stdout) FLUSH;
  277.  
  278.     kill_mentioned = FALSE;
  279.     if (localkfp)
  280.         intr = do_kfile(localkfp,entering);
  281.     if (globkfp && !intr)
  282.         intr = do_kfile(globkfp,entering);
  283.     putchar('\n') FLUSH;
  284.     if (entering && kill_mentioned && novice_delays)
  285. #ifdef VERBOSE
  286.         IF(verbose)
  287.         get_anything();
  288.         ELSE
  289. #endif
  290. #ifdef TERSE
  291.         pad(just_a_sec);
  292. #endif
  293.     if (anytokill)            /* if there was anything to kill */
  294.         forcelast = FALSE;        /* allow for having killed it all */
  295.     firstart = oldfirst;
  296.     }
  297.     if (!entering && localkf_changes && !intr)
  298.     rewrite_kfile(lastart);
  299.     mode = oldmode;
  300. }
  301.  
  302. static FILE *newkfp;
  303.  
  304. static void write_thread_commands(data, extra)
  305. HASHDATUM *data;
  306. int extra;
  307. {
  308.     register ARTICLE *ap = (data->dat_ptr? (ARTICLE*)data->dat_ptr
  309.                     : article_ptr(data->dat_len));
  310.     register int flags;
  311.     char ch;
  312.  
  313.     if (flags = (ap->flags & AF_AUTOFLAGS)) {
  314.     if (!(ap->flags & AF_MISSING) || ap->child1) {
  315.         if (flags & AF_AUTOKILLALL)
  316.         ch = 'J';
  317.         else if (flags & AF_AUTOKILL)
  318.         ch = ',';
  319.         else if (flags & AF_AUTOSELECTALL)
  320.         ch = '+';
  321.         else if (flags & AF_AUTOSELECT)
  322.         ch = '.';
  323.         fprintf(newkfp,"%s T%c\n", ap->msgid, ch);
  324.     }
  325.     }
  326. }
  327.  
  328. void
  329. rewrite_kfile(thru)
  330. ART_NUM thru;
  331. {
  332.     bool no_kills = 0, has_star_commands = FALSE;
  333.  
  334.     if (localkfp) {
  335.     fseek(localkfp,0L,0);        /* rewind current file */
  336.     /* If we're writing ids, we know the file is not null */
  337.     if (localkf_changes > 1)
  338.         ;
  339.     else if (fgets(buf,LBUFLEN,localkfp) != Nullch
  340.      && (strnNE(buf,"THRU",4) || fgets(buf,LBUFLEN,localkfp) != Nullch))
  341.         fseek(localkfp,0L,0);
  342.     else
  343.         no_kills = 1;
  344.     }
  345.     strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
  346.     if (!localkfp)
  347.     makedir(buf,MD_FILE);
  348.     UNLINK(buf);            /* to prevent file reuse */
  349.     if (no_kills)
  350.     open_kfile(KF_LOCAL);        /* close file and reset open flag */
  351.     else if (newkfp = fopen(buf,"w")) {
  352.     fprintf(newkfp,"THRU %ld\n",(long)thru);
  353.     while (localkfp && fgets(buf,LBUFLEN,localkfp) != Nullch) {
  354.         if (strnEQ(buf,"THRU",4))
  355.         continue;
  356.         /* Write star commands after other kill commands */
  357.         if (*buf == '*') {
  358.         has_star_commands = TRUE;
  359.         continue;
  360.         }
  361.         /* Leave out any outdated thread commands */
  362.         if (*buf != 'T' && *buf != '<')
  363.         fputs(buf,newkfp);
  364.     }
  365.     if (has_star_commands) {
  366.         fseek(localkfp,0L,0);            /* rewind file */
  367.         while (fgets(buf,LBUFLEN,localkfp) != Nullch) {
  368.         if (*buf == '*')
  369.             fputs(buf,newkfp);
  370.         }
  371.     }
  372.     /* Append all the still-valid thread commands */
  373.     hashwalk(msgid_hash, write_thread_commands, 0);
  374.     fclose(newkfp);
  375.     open_kfile(KF_LOCAL);        /* and reopen local file */
  376.     }
  377.     else
  378.     printf(cantcreate,buf) FLUSH;
  379.     localkf_changes = 0;
  380.     has_normal_kills = FALSE;
  381. }
  382.  
  383. /* edit KILL file for newsgroup */
  384.  
  385. int
  386. edit_kfile()
  387. {
  388.     int r = -1;
  389.  
  390.     if (in_ng) {
  391.     register SUBJECT *sp;
  392.  
  393.     if (localkf_changes)
  394.         rewrite_kfile(lastart);
  395.     for (sp = first_subject; sp; sp = sp->next)
  396.         clear_subject(sp);
  397.     localkf_changes = 0;
  398.     strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
  399.     } else
  400.     strcpy(buf,filexp(getval("KILLGLOBAL",killglobal)));
  401.     if ((r = makedir(buf,MD_FILE)) >= 0) {
  402.     sprintf(cmd_buf,"%s %s",
  403.         filexp(getval("VISUAL",getval("EDITOR",defeditor))),buf);
  404.     printf("\nEditing %s KILL file:\n%s\n",
  405.         (in_ng?"local":"global"),cmd_buf) FLUSH;
  406.     resetty();            /* make sure tty is friendly */
  407.     r = doshell(sh,cmd_buf);/* invoke the shell */
  408.     noecho();            /* and make terminal */
  409.     crmode();            /*   unfriendly again */
  410.     open_kfile(in_ng);
  411.     if (localkfp) {
  412.         fseek(localkfp,0L,0);            /* rewind file */
  413.         has_normal_kills = FALSE;
  414.         while (fgets(buf,LBUFLEN,localkfp) != Nullch) {
  415.         if (*buf == '/' || *buf == '*')
  416.             has_normal_kills = TRUE;
  417.         else if (*buf == '<') {
  418.             register ARTICLE *ap;
  419.             char *cp = index(buf,' ');
  420.             if (!cp)
  421.             cp = ",";
  422.             else
  423.             *cp++ = '\0';
  424.             if ((ap = get_article(buf)) != Nullart) {
  425.             if (*cp == 'T')
  426.                 cp++;
  427.             switch (*cp) {
  428.             case '+':
  429.                 ap->flags |= AF_AUTOSELECTALL;
  430.                 break;
  431.             case '.':
  432.                 ap->flags |= AF_AUTOSELECT;
  433.                 break;
  434.             case 'J':
  435.             case 'j':
  436.                 ap->flags |= AF_AUTOKILLALL;
  437.                 break;
  438.             case ',':
  439.                 ap->flags |= AF_AUTOKILL;
  440.                 break;
  441.             }
  442.             }
  443.         }
  444.         }
  445.     }
  446.     }
  447.     else
  448.     printf("Can't make %s\n",buf) FLUSH;
  449.     return r;
  450. }
  451.  
  452. void
  453. open_kfile(local)
  454. int local;
  455. {
  456.     char *kname = filexp(local ?
  457.     getval("KILLLOCAL",killlocal) :
  458.     getval("KILLGLOBAL",killglobal)
  459.     );
  460.     
  461.     /* delete the file if it is empty */
  462.     if (stat(kname,&filestat) >= 0 && !filestat.st_size)
  463.     UNLINK(kname);
  464.     if (local) {
  465.     if (localkfp)
  466.         fclose(localkfp);
  467.     localkfp = fopen(kname,"r");
  468.     }
  469.     else {
  470.     if (globkfp)
  471.         fclose(globkfp);
  472.     globkfp = fopen(kname,"r");
  473.     }
  474. }
  475.  
  476. void
  477. kf_append(cmd)
  478. char *cmd;
  479. {
  480.     strcpy(cmd_buf,filexp(getval("KILLLOCAL",killlocal)));
  481.     if (makedir(cmd_buf,MD_FILE) >= 0) {
  482. #ifdef VERBOSE
  483.     IF(verbose)
  484.         printf("\nDepositing command in %s...",cmd_buf);
  485.     ELSE
  486. #endif
  487. #ifdef TERSE
  488.         printf("\n--> %s...",cmd_buf);
  489. #endif
  490.     fflush(stdout);
  491.     if (novice_delays)
  492.         sleep(2);
  493.     if ((tmpfp = fopen(cmd_buf,"a")) != Nullfp) {
  494.         fseek(tmpfp,0L,2);        /* get to EOF for sure */
  495.         fprintf(tmpfp,"%s\n",cmd);
  496.         fclose(tmpfp);
  497.         fputs("done\n",stdout) FLUSH;
  498.     }
  499.     else
  500.         printf(cantopen,cmd_buf) FLUSH;
  501.     }
  502.     has_normal_kills = TRUE;
  503. }
  504. #endif /* KILLFILES */
  505.