home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume30 / tin / part13 / active.c next >
C/C++ Source or Header  |  1992-05-20  |  9KB  |  385 lines

  1. /*
  2.  *  Project   : tin - a threaded Netnews reader
  3.  *  Module    : active.c
  4.  *  Author    : I.Lea
  5.  *  Created   : 16-02-92
  6.  *  Updated   : 02-05-92
  7.  *  Notes     :
  8.  *  Copyright : (c) Copyright 1991-92 by Iain Lea
  9.  *              You may  freely  copy or  redistribute  this software,
  10.  *              so  long as there is no profit made from its use, sale
  11.  *              trade or  reproduction.  You may not change this copy-
  12.  *              right notice, and it must be included in any copy made
  13.  */
  14.  
  15. #include    "tin.h"
  16.  
  17. int group_hash[TABLE_SIZE];            /* group name --> active[] */
  18. int reread_active_file = FALSE;
  19.  
  20.  
  21. /*
  22.  *  Resync active file when SIGALRM signal received that
  23.  *  is triggered by alarm (RESYNC_ACTIVE_SECS) call.
  24.  */
  25.  
  26. void resync_active_file ()
  27. {
  28.     if (reread_active_file) {
  29.         free_active_arrays ();
  30.         max_active = DEFAULT_ACTIVE_NUM;
  31.         expand_active ();
  32.         read_active_file ();
  33.         read_newsrc (TRUE);
  34.         set_alarm_signal ();
  35.         group_selection_page ();
  36.     }
  37. }
  38.  
  39. /*
  40.  *  Load the active file into active[] and create copy of active ~/.tin/active
  41.  */
  42.  
  43. int read_active_file ()
  44. {
  45.     FILE *fp;
  46.     char *p, *q, *r;
  47.     char buf[LEN];
  48.     char moderated = 'y';
  49.     int created, i;
  50.     long h;
  51.     
  52.     num_active = 0;
  53.  
  54.     if (! update) {
  55.         wait_message (txt_reading_active_file);
  56.     }
  57.  
  58.     if ((fp = open_active_fp ()) == NULL) {
  59.         if (compiled_with_nntp) {
  60.             sprintf (msg, txt_cannot_open_active_file, active_file, progname);
  61.             wait_message (msg);
  62.         } else {
  63.             fputc ('\n', stderr);
  64.             fprintf (stderr, txt_cannot_open, active_file);
  65.             fputc ('\n', stderr);
  66.             fflush (stderr);
  67.         }
  68.         exit (1);
  69.     }
  70.  
  71.     for (i = 0; i < TABLE_SIZE; i++) {
  72.         group_hash[i] = -1;
  73.     }
  74.  
  75.     while (fgets (buf, sizeof (buf), fp) != NULL) {
  76.         for (p = buf; *p && *p != ' '; p++)
  77.             continue;
  78.         if (*p != ' ') {
  79.             error_message (txt_bad_active_file, buf);
  80.             continue;
  81.         }
  82.         *p++ = '\0';
  83.  
  84.         if (num_active >= max_active) {
  85.             debug_nntp ("read_active_file", "EXPANDING active file");
  86.             expand_active ();
  87.         }
  88.  
  89.         h = hash_groupname (buf);
  90.  
  91.         if (group_hash[h] == -1) {
  92.             group_hash[h] = num_active;
  93.         } else {                /* hash linked list chaining */
  94.             for (i=group_hash[h]; active[i].next >= 0; i=active[i].next) {
  95.                 if (strcmp(active[i].name, buf) == 0) {
  96.                     goto read_active_continue;        /* kill dups */
  97.                 }
  98.             }
  99.             if (strcmp(active[i].name, buf) == 0)
  100.                 goto read_active_continue;
  101.             active[i].next = num_active;
  102.         }
  103.  
  104.         for (q = p; *q && *q != ' '; q++)
  105.             continue;
  106.         if (*q != ' ') {
  107.             error_message (txt_bad_active_file, buf);
  108.             continue;
  109.         }
  110.         *q++ = '\0';
  111.  
  112.         for (r = q; *r && *r != '\n'; r++) {
  113.             if (*r == 'y' || *r == 'm') {
  114.                 moderated = *r;
  115.                 break;
  116.             }
  117.         }
  118.  
  119.         /*
  120.          * Group info.
  121.          */
  122.         active[num_active].name = str_dup (buf);
  123.         active[num_active].max = (long) atol (p);
  124.         active[num_active].min = (long) atol (q);
  125.         active[num_active].moderated = moderated;
  126.         active[num_active].next = -1;            /* hash chaining */
  127.         active[num_active].flag = UNSUBSCRIBED;    /* not in my_group[] yet */
  128.         /*
  129.          * Per group attributes
  130.          */
  131.         active[num_active].attribute.server  = (char *) 0;
  132.         active[num_active].attribute.maildir = default_maildir;
  133.         active[num_active].attribute.savedir = default_savedir;
  134.         active[num_active].attribute.sigfile = default_sigfile;
  135.         active[num_active].attribute.read    = FALSE;    /* read/unread */
  136.         active[num_active].attribute.showall = show_only_unread;
  137.         active[num_active].attribute.thread  = thread_arts;
  138.         active[num_active].attribute.sortby  = sort_art_type;
  139.         active[num_active].attribute.author  = show_author;
  140.         active[num_active].attribute.autosave= save_archive_name;
  141.         active[num_active].attribute.process = post_proc_type; 
  142.  
  143.         num_active++;
  144.  
  145. read_active_continue:;
  146.  
  147.     }
  148.     fclose (fp);
  149.  
  150.     /*
  151.      *  exit if active file is empty
  152.      */
  153.     if (! num_active) {
  154.         error_message (txt_active_file_is_empty, active_file);
  155.         exit (1);
  156.     }
  157.  
  158.     /*
  159.      *  create backup of LIBDIR/active for use by -n option to notify new groups 
  160.      */
  161.     created = backup_active (TRUE);
  162.  
  163.     debug_print_active ();
  164.  
  165.     if (cmd_line && (read_news_via_nntp && update == FALSE)) {
  166.         if (! (update && ! verbose)) {
  167.             wait_message ("\n");
  168.         }
  169.     }
  170.  
  171.     return (created);
  172. }
  173.  
  174. /*
  175.  *  create ~/.tin/active from LIBDIR/active if it does not exist 
  176.  */
  177.  
  178. int backup_active (create)
  179.     int create;
  180. {
  181.     char buf[LEN];
  182.     FILE *fp;
  183.     int created = FALSE;
  184.     int i;
  185.     struct stat sb;
  186.     
  187.     sprintf (buf, "%s/active", rcdir);
  188.     
  189.     if (create) {
  190.         if (stat (buf, &sb) != -1) {
  191.             goto backup_active_done;
  192.         }
  193.     }
  194.     
  195.     if ((fp = fopen (buf, "w")) != NULL) {
  196.         for (i = 0; i < num_active ; i++) {    /* for each group */
  197.             fprintf (fp, "%s\n", active[i].name);
  198.         }
  199.         fclose (fp);
  200.         chmod (buf, 0644);
  201.         created = TRUE;
  202.     }
  203.  
  204. backup_active_done:
  205.     return (created);
  206. }
  207.  
  208. /*
  209.  *  Option -n to check for any newly created newsgroups.
  210.  */
  211.  
  212. void notify_groups ()
  213. {
  214.     char buf[LEN];
  215.     FILE *fp;
  216.     int group_not_found;
  217.     int index;
  218.     int num = 0;
  219.     int update_old_active = FALSE;
  220.     int max_old_active;
  221.     register int i, j;
  222.     struct notify_t {
  223.         char name[LEN];
  224.         int len;
  225.         int visited;
  226.     } *old_active = (struct notify_t *) 0;
  227.     
  228.     sprintf (buf, "%s/active", rcdir);
  229.     
  230.     if ((fp = fopen (buf, "r")) == NULL) {
  231.         perror_message (txt_cannot_open, buf);
  232.         goto notify_groups_done;
  233.     }
  234.  
  235.     Raw (TRUE);
  236.     
  237.     wait_message (txt_checking_active_file);
  238.  
  239.     max_old_active = num_active;
  240.     
  241.     old_active = (struct notify_t *) my_malloc ((unsigned) sizeof (struct notify_t) * max_old_active);
  242.     if (old_active == (struct notify_t *) 0) {
  243.         error_message (txt_out_of_memory, progname);
  244.         goto notify_groups_done;
  245.     }
  246.     
  247.     while (fgets (old_active[num].name, sizeof (old_active[num].name), fp) != NULL) {
  248.         old_active[num].len = strlen (old_active[num].name)-1;
  249.         old_active[num].name[old_active[num].len] = '\0';
  250.         old_active[num].visited = FALSE;
  251.         num++;
  252.         if (num >= max_old_active) {
  253.             max_old_active= max_old_active + (max_old_active / 2);
  254.             old_active= (struct notify_t*) my_realloc(
  255.                 (char *) old_active, 
  256.                 (unsigned) sizeof(struct notify_t) * max_old_active);
  257.             if (old_active == (struct notify_t *) 0) {
  258.                 error_message (txt_out_of_memory, progname);
  259.                 goto notify_groups_done;
  260.             }
  261.         }
  262.     }
  263.  
  264.     for (i = 0 ; i < num_active ; i++) {    
  265.         group_not_found = TRUE;
  266.         for (j=0; j < num ; j++) {
  267.             if (strcmp (old_active[j].name, active[i].name) == 0) {
  268.                 group_not_found = FALSE;    /* found it so read in next group */
  269.                 old_active[j].visited = TRUE;
  270.                 break;
  271.             }
  272.         }
  273.  
  274.         if (group_not_found == FALSE) {
  275.             continue;
  276.         }    
  277.  
  278.         update_old_active = TRUE;
  279.         do {
  280.             fputc ('\r', stdout);
  281.             CleartoEOLN();
  282.             printf (txt_subscribe_to_new_group, active[i].name);
  283.             fflush (stdout);
  284.             buf[0] = ReadCh();
  285.         } while (buf[0] != 'y' && buf[0] != 'n');
  286.             
  287.         if (buf[0] == 'y') {
  288.             index = add_group (active[i].name, TRUE);
  289.             subscribe (active[my_group[index]].name, ':',
  290.                    my_group[index], FALSE);
  291.         }
  292.         printf ("\r\n%s", txt_checking);
  293.         fflush (stdout);
  294.     }
  295.     fclose (fp);
  296.     fputc ('\r', stdout);
  297.     fflush (stdout);
  298.     CleartoEOLN();
  299.  
  300.     /*
  301.      * Look for bogus groups 
  302.      */
  303.     for (j = 0 ; j < num ; j++)  {
  304.         if (old_active[j].visited) {
  305.             continue;
  306.         }
  307.         do {    
  308.             update_old_active= 1;
  309.             fputc ('\r', stdout);
  310.             CleartoEOLN ();
  311.             printf (txt_delete_bogus_group, old_active[j].name);
  312.             fflush (stdout);
  313.             buf[0] = ReadCh ();
  314.         } while (buf[0] != 'y' && buf[0] != 'n');
  315.         if (buf[0] == 'y') {
  316.             delete_group (old_active[j].name);
  317.         }
  318.         printf ("\r\n");
  319.     }
  320.     
  321.     Raw (TRUE);
  322.  
  323.     /*
  324.      *  write active[] to ~/.tin/active
  325.      */
  326.     if (update_old_active) {
  327.         backup_active (FALSE);
  328.     }
  329.  
  330. notify_groups_done:
  331.     if (old_active != (struct notify_t *) 0) {
  332.         free ((char *) old_active);
  333.         old_active = (struct notify_t *) 0;
  334.     }
  335. }
  336.  
  337. /*
  338.  *  Mark any groups in my_group[] that are in ~/.tin/unthread so they
  339.  *  will not be threaded
  340.  */
  341.  
  342. void mark_unthreaded_groups ()
  343. {
  344.     FILE *fp;
  345.     char buf[LEN];
  346.     int i, len;
  347.     long h;
  348.  
  349. #ifndef INDEX_DAEMON
  350.  
  351.     if ((fp = fopen (unthreadfile, "r")) == NULL) {
  352.         perror_message (txt_cannot_open, unthreadfile);
  353.         return;
  354.     }
  355.  
  356.     while (fgets (buf, sizeof (buf), fp) != NULL) {
  357.         buf[strlen (buf)-1] = '\0'; 
  358.         h = hash_groupname (buf);
  359.         sprintf (msg, "Unthreading %s...\n", buf);
  360.         wait_message (msg);
  361.         
  362.         i = group_hash[h];
  363.         
  364.         if (active[i].next == -1) {
  365.             len = strlen (active[i].name);
  366.             if (strncmp (active[i].name, buf, len) == 0) {
  367.                 active[i].attribute.thread = FALSE;
  368.             }
  369.         
  370.         } else {
  371.             for (i=group_hash[h]; active[i].next >= 0; i=active[i].next) {
  372.                 len = strlen (active[i].name);
  373.                 if (strncmp (active[i].name, buf, len) == 0) {
  374.                     active[i].attribute.thread = FALSE;
  375.                     break;
  376.                 }
  377.             }
  378.         }    
  379.     }
  380.  
  381.     fclose (fp);
  382. #endif /* INDEX_DAEMON */
  383. }
  384.  
  385.