1 /*
2  *	(c) Copyright 1990, Kim Fabricius Storm.  All rights reserved.
3  *      Copyright (c) 1996-2005 Michael T Pins.  All rights reserved.
4  *
5  *	read/update incore copy of active file
6  */
7 
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include "config.h"
12 #include "global.h"
13 #include "active.h"
14 #include "db.h"
15 #include "master.h"
16 #include "newsrc.h"
17 
18 void
read_active_file(FILE * act,FILE * copy)19 read_active_file(FILE * act, FILE * copy)
20 {
21     char            line[512];
22     register char  *cp, *name;
23     register group_header *gh, *gh1;
24     int             must_update;
25     register flag_type old_flag;
26 
27     Loop_Groups_Header(gh) {
28 	gh->master_flag &= ~M_VALID;
29 	gh->first_a_article = 0;
30 	gh->last_a_article = 0;
31     }
32 
33     while (fgets(line, 512, act)) {
34 	if (copy != NULL)
35 	    fputs(line, copy);
36 	must_update = 0;
37 
38 	cp = line;
39 	while (*cp && isspace(*cp))
40 	    cp++;		/* eat blank lines */
41 	if (*cp == NUL || *cp == '#')
42 	    continue;
43 
44 	/* cp -> NAME space 00888 ... nl */
45 	name = cp;
46 	while (*cp != ' ')
47 	    cp++;
48 	*cp++ = NUL;
49 
50 	gh = lookup_no_alias(name);
51 	if (gh == NULL) {
52 	    /* new group */
53 	    gh = add_new_group(name);
54 	    if (gh == NULL)
55 		continue;
56 	    must_update = 1;
57 	}
58 	while (*cp && isspace(*cp))
59 	    cp++;
60 	gh->last_a_article = atol(cp);
61 
62 	while (*cp && isdigit(*cp))
63 	    cp++;
64 	while (*cp && isspace(*cp))
65 	    cp++;
66 
67 	if (*cp == NUL) {
68 	    log_entry('E', "Error in active file for entry %s", name);
69 	    continue;
70 	}
71 	gh->first_a_article = atol(cp);
72 	if (gh->first_a_article == 0)
73 	    gh->first_a_article = 1;
74 	while (*cp && isdigit(*cp))
75 	    cp++;
76 	while (*cp && isspace(*cp))
77 	    cp++;
78 
79 	gh->master_flag |= M_VALID;
80 	if (gh->master_flag & M_IGNORE_G)
81 	    continue;
82 
83 	old_flag = gh->master_flag &
84 	    (M_IGNORE_A | M_MODERATED | M_NOPOST | M_ALIASED);
85 	gh->master_flag &=
86 	    ~(M_IGNORE_A | M_MODERATED | M_NOPOST | M_ALIASED);
87 
88 	switch (*cp) {
89 	    default:
90 		break;
91 
92 	    case 'x':
93 		gh->master_flag |= M_IGNORE_A;
94 		if ((old_flag & (M_IGNORE_A | M_ALIASED)) == M_IGNORE_A)
95 		    continue;
96 		must_update++;
97 		break;
98 
99 	    case 'm':
100 		gh->master_flag |= M_MODERATED;
101 		if (old_flag & M_MODERATED)
102 		    continue;
103 		must_update++;
104 		break;
105 
106 	    case 'n':
107 		gh->master_flag |= M_NOPOST;
108 		if (old_flag & M_NOPOST)
109 		    continue;
110 		must_update++;
111 		break;
112 
113 	    case '=':
114 		while (*++cp && isspace(*cp))
115 		    cp++;
116 		name = cp;
117 		while (*cp && !isspace(*cp))
118 		    cp++;
119 		*cp = NUL;
120 		if (old_flag & M_ALIASED) {
121 		    /* quick check: has the alias changed */
122 		    int32           n = (int32) gh->data_write_offset;
123 		    if (n >= 0 && n < master.number_of_groups) {
124 			gh1 = ACTIVE_GROUP(n);
125 			if (strcmp(gh1->group_name, name) == 0) {
126 			    gh->master_flag |= M_ALIASED | M_IGNORE_A;
127 			    continue;
128 			}
129 		    }
130 		}
131 		gh1 = lookup_no_alias(name);
132 		if (gh1 == NULL) {
133 		    /* '=unknown.group' is treated just like 'x' */
134 		    if ((old_flag & M_IGNORE_A) == 0)
135 			log_entry('R', "Group %s aliased to unknown group (%s)",
136 				  gh->group_name, name);
137 		    gh->master_flag |= M_IGNORE_A;
138 		    if ((old_flag & (M_IGNORE_A | M_ALIASED)) == M_IGNORE_A)
139 			continue;
140 		} else {
141 		    gh->master_flag |= M_ALIASED | M_IGNORE_A;
142 		    gh->data_write_offset = (long) gh1->group_num;
143 		}
144 		must_update = 1;
145 		break;
146 	}
147 
148 	if ((old_flag & M_ALIASED) && (gh->master_flag & M_ALIASED) == 0) {
149 	    gh->data_write_offset = 0;
150 	    gh->master_flag |= M_MUST_CLEAN;
151 	    continue;
152 	}
153 	if (must_update && who_am_i == I_AM_MASTER)
154 	    db_write_group(gh);
155     }
156 }
157