1 | #! /usr/bin/perl |
---|
2 | ## $Revision: 1.9 $ |
---|
3 | ## Script to execute checkgroups text; results to stdout. |
---|
4 | |
---|
5 | ## Author: Lutz.Donnerhacke@Jena.Thur.De |
---|
6 | ## 2000-05-03: file-locking and sanity checks (Urs Janssen <urs@tin.org>) |
---|
7 | ## 2000-04-10: & in descriptions weren't quoted (Urs Janssen <urs@tin.org>) |
---|
8 | ## 2000-04-01: Added scope support. (Sven Paulus <sven@nntp.de>) |
---|
9 | ## Removed 14 character limit. (Sven Paulus <sven@nntp.de>) |
---|
10 | ## 1999-10-06: Fixed moderated bug. (Urs Janssen <urs@tin.org>) |
---|
11 | ## 1999-07-05: Fixed moderated bug. |
---|
12 | ## 1998-08-17: Added output of old descriptions. |
---|
13 | ## 1998-08-12: first version |
---|
14 | |
---|
15 | ## =()<. @<_PATH_SHELLVARS>@>()= |
---|
16 | $pshellvars="/usr/lib/news/innshellvars"; |
---|
17 | |
---|
18 | open(CONFIG,"<$pshellvars") || die "Can't read config: $!\n"; |
---|
19 | while (<CONFIG>) { |
---|
20 | chop; |
---|
21 | if(($name,$val) = /^([A-Z]+)=(.+)$/) { |
---|
22 | $val =~ s/\$\{([A-Z]+(-([^}]+))?)\}/$ENV{$1} || $3/eg; |
---|
23 | $ENV{$name} = $val; |
---|
24 | } |
---|
25 | } |
---|
26 | close(CONFIG); |
---|
27 | |
---|
28 | ## wildmat(2) |
---|
29 | sub wildmat { |
---|
30 | local($text,$pattern) = @_; |
---|
31 | |
---|
32 | # escape regex metachars but not glob chars |
---|
33 | $pattern =~ s:([.+^\${}|()\@\\]):\\$1:g; |
---|
34 | # and wildcards to regex |
---|
35 | $pattern =~ s/\*/.*/g; |
---|
36 | $pattern =~ s/\?/.?/g; |
---|
37 | # $pattern =~ s/^/^/; |
---|
38 | $pattern =~ s/$/\$/; |
---|
39 | return ($text =~ /$pattern/); |
---|
40 | } |
---|
41 | |
---|
42 | ## scope match (@patterns is defined below, global array) |
---|
43 | sub match { |
---|
44 | local($text) = @_; |
---|
45 | $match = 0; |
---|
46 | |
---|
47 | foreach $pattern (@patterns) { |
---|
48 | if ($pattern =~ /^!(.*)/) { |
---|
49 | $match &= !&wildmat($text,$1); |
---|
50 | } else { |
---|
51 | $match |= &wildmat($text,$pattern); |
---|
52 | } |
---|
53 | } |
---|
54 | return $match; |
---|
55 | } |
---|
56 | |
---|
57 | ## Copy the article without headers, append local newsgroups. |
---|
58 | $header = 1; |
---|
59 | while (<STDIN>) { |
---|
60 | chomp; |
---|
61 | if ($header && /^$/) { |
---|
62 | $header = 0; |
---|
63 | $pattern = "*" unless defined $pattern; |
---|
64 | @patterns = split(/,/,$pattern); |
---|
65 | next; |
---|
66 | } |
---|
67 | if ($header && /^Control:\s+checkgroups\s+(.*)/i) { |
---|
68 | @elements = split(/\s+/,$1); |
---|
69 | foreach $a (@elements) { |
---|
70 | last if ($a =~ /^#/); |
---|
71 | $pattern .= "," if defined $pattern; |
---|
72 | $pattern .= $a; |
---|
73 | $pattern .= ".*" unless ($a =~ /[,\*]/); |
---|
74 | } |
---|
75 | } |
---|
76 | next if $header; |
---|
77 | last if (/^-- $/); |
---|
78 | if(! /^\S+\.(\d+|\.all)(\s|\.)/i && |
---|
79 | /^(([^W_][-+\w]*)(\.[^W_][-+\w]*)+)\s+(\S.*)/) { |
---|
80 | next unless &match($1); |
---|
81 | $tlh{$2} = 1; |
---|
82 | $newsgroups{$1} = $4; |
---|
83 | $existing{$1} = 1; |
---|
84 | } else { |
---|
85 | $unparsable .= '# ' . $_ . "\n" if (! /^#/); |
---|
86 | } |
---|
87 | } |
---|
88 | |
---|
89 | if($unparsable) { |
---|
90 | print "# Entries violating common newsgroup conventions:\n"; |
---|
91 | print $unparsable; |
---|
92 | print "\n"; |
---|
93 | } |
---|
94 | |
---|
95 | ## Additional groups in those hierarchies... |
---|
96 | if(-s $ENV{'LOCALGROUPS'}) { |
---|
97 | open(LOCAL, '<'.$ENV{'LOCALGROUPS'}); |
---|
98 | while(<LOCAL>) { |
---|
99 | chop; |
---|
100 | # if(/^(([^.]+)\.\S+)\s+(\S.*)/) { |
---|
101 | if(/^(([^W_][-+\w]*)(?:\.[^W_][-+\w]*)+)\s+(\S.*)/) { |
---|
102 | next unless defined $tlh{$2}; |
---|
103 | next unless &match($1); |
---|
104 | $newsgroups{$1} = $3; |
---|
105 | $existing{$1} = 1; |
---|
106 | } |
---|
107 | } |
---|
108 | close(LOCAL); |
---|
109 | } |
---|
110 | |
---|
111 | print "# To process this file pipe it though the following command:\n"; |
---|
112 | print "# ", $ENV{'SED'}, " '1,/^\$/d' | su news\n"; |
---|
113 | |
---|
114 | print $ENV{'NEWSBIN'}, "/ctlinnd throttle Checkgroups-\$\$\n\n"; |
---|
115 | |
---|
116 | #####B################################################################### |
---|
117 | # checking active |
---|
118 | ######################################################################## |
---|
119 | open(ACTIVE,'<'.$ENV{'ACTIVE'}) || die "Can't read active '".$ENV{'ACTIVE'}."'\n"; |
---|
120 | while(<ACTIVE>) { |
---|
121 | # if(($group, $tlh, $mode) = /^(([^.]+)\.\S+)\s\d+\s\d+\s([ynmx])/) { |
---|
122 | if(($group, $tlh, $mode) = /^(([^W_][-+\w]*)(?:\.[^W_][-+\w]*)+)\s\d+\s\d+\s([ynmx])/) { |
---|
123 | next unless $tlh{$tlh}; |
---|
124 | next unless &match($group); |
---|
125 | push(@remove, $group), next unless $newsgroups{$group}; |
---|
126 | delete $existing{$group}; |
---|
127 | # if($newsgroups{$group} =~ / \(Moderated\)\s*/) { |
---|
128 | if($newsgroups{$group} =~ /\(Moderated\)\s*/) { # don't require a sapce befor (Moderated) , as this will fail for tw.* |
---|
129 | push(@mod, $group) if $mode eq 'y'; |
---|
130 | } else { |
---|
131 | push(@unmod, $group) if $mode eq 'm'; |
---|
132 | } |
---|
133 | } |
---|
134 | } |
---|
135 | close(ACTIVE); |
---|
136 | |
---|
137 | if($#remove >= 0) { |
---|
138 | print "# The following newsgroups are non-standard.\n"; |
---|
139 | foreach $group (sort @remove) { |
---|
140 | print $ENV{'NEWSBIN'}, '/ctlinnd rmgroup ', $group, "\n"; |
---|
141 | } |
---|
142 | print "\n"; |
---|
143 | } |
---|
144 | undef @remove; |
---|
145 | |
---|
146 | foreach $group (keys %existing) { |
---|
147 | push @add, $group; |
---|
148 | } |
---|
149 | undef %existing; |
---|
150 | |
---|
151 | if($#add >= 0) { |
---|
152 | print "# The following newsgroups were missing and should be added.\n"; |
---|
153 | foreach $group (sort @add) { |
---|
154 | print $ENV{'NEWSBIN'}, '/ctlinnd newgroup ', $group, ' '; |
---|
155 | $group =~ /^([^.])\.(.*)$/; |
---|
156 | if($newsgroups{$group} =~ / \(Moderated\)\s*/) { |
---|
157 | print 'm'; |
---|
158 | } else { |
---|
159 | print 'y'; |
---|
160 | } |
---|
161 | printf ("%s\n", (defined ($ENV{'FROM'}) ? $ENV{'FROM'} : "")); |
---|
162 | } |
---|
163 | print "\n"; |
---|
164 | } |
---|
165 | undef @add; |
---|
166 | |
---|
167 | ######################################################################## |
---|
168 | # checking newsgroups |
---|
169 | ######################################################################## |
---|
170 | open(NEWSGROUPS,'<'.$ENV{'NEWSGROUPS'}) || die "Can't read newsgroups '".$ENV{'NEWSGROUPS'}."'\n"; |
---|
171 | while(<NEWSGROUPS>) { |
---|
172 | chop; |
---|
173 | if(($group,$tlh,$description) = /^(([^W_][-+\w]*)(?:\.[^W_][-+\w]*)+)\s+(\S.*)$/) { |
---|
174 | next unless defined $tlh{$tlh}; |
---|
175 | next unless &match($group); |
---|
176 | if(defined $newsgroups{$group}) { |
---|
177 | if($newsgroups{$group} ne $description) { |
---|
178 | $sed .= " # ${group} ${description}\n"; |
---|
179 | $newsgroups{$group} =~ s-/-\\/-g; |
---|
180 | $newsgroups{$group} =~ s-&-\\&-g; |
---|
181 | $sed .= " /^${group}[ \t]/s/[ \t].*\$/\t".$newsgroups{$group}."/\n"; |
---|
182 | } |
---|
183 | } else { |
---|
184 | $sed .= " /^${group}[ \t]/d\n"; |
---|
185 | } |
---|
186 | delete $newsgroups{$group}; |
---|
187 | } |
---|
188 | } |
---|
189 | close(NEWSGROUPS); |
---|
190 | |
---|
191 | if(defined $sed) { |
---|
192 | $printlock = 1; |
---|
193 | print ". $pshellvars\n"; |
---|
194 | print "LOCK=\${LOCKS}/LOCK.newsgroups\n"; |
---|
195 | print "PID=\$\$\n"; |
---|
196 | print "TRY=0\n"; |
---|
197 | print "MAXTRY=60\n"; |
---|
198 | print "export LOCK MAXTRY PID LOGFILE TRY\n"; |
---|
199 | print "while [ \${TRY} -lt \${MAXTRY} ]; do\n"; |
---|
200 | print "\tshlock -p \${PID} -f \${LOCK} && break\n"; |
---|
201 | print "\tsleep 2\n"; |
---|
202 | print "\tTRY=`expr \${TRY} + 1`\n"; |
---|
203 | print "done\n"; |
---|
204 | print "test \${TRY} -lt \${MAXTRY} || {\n"; |
---|
205 | print "\techo \"Newgroup cannot update newsgroups. Locked by\" `cat \${LOCK}` 1>&2\n"; |
---|
206 | print "\texit\n"; |
---|
207 | print "}\n\n"; |
---|
208 | |
---|
209 | print "# The following modifications on your newsgroups file are necessary.\n"; |
---|
210 | print $ENV{'SED'}, " '\n"; |
---|
211 | $sed =~ s/'/'\\''/g; |
---|
212 | print $sed, " ' < ", $ENV{'NEWSGROUPS'}, ' > /tmp/$$',"\n"; |
---|
213 | print 'cp /tmp/$$ ', $ENV{'NEWSGROUPS'}, "\n"; |
---|
214 | print 'rm -f /tmp/$$',"\n\n"; |
---|
215 | } |
---|
216 | |
---|
217 | foreach $group (sort keys %newsgroups) { |
---|
218 | if (!defined($printlock)) { |
---|
219 | $printlock=1; |
---|
220 | print ". $pshellvars\n"; |
---|
221 | print "LOCK=\${LOCKS}/LOCK.newsgroups\n"; |
---|
222 | print "PID=\$\$\n"; |
---|
223 | print "TRY=0\n"; |
---|
224 | print "MAXTRY=60\n"; |
---|
225 | print "export LOCK MAXTRY PID LOGFILE TRY\n"; |
---|
226 | print "while [ \${TRY} -lt \${MAXTRY} ]; do\n"; |
---|
227 | print "\tshlock -p \${PID} -f \${LOCK} && break\n"; |
---|
228 | print "\tsleep 2\n"; |
---|
229 | print "\tTRY=`expr \${TRY} + 1`\n"; |
---|
230 | print "done\n"; |
---|
231 | print "test \${TRY} -lt \${MAXTRY} || {\n"; |
---|
232 | print "\techo \"Newgroup cannot update newsgroups. Locked by\" `cat \${LOCK}` 1>&2\n"; |
---|
233 | print "\texit\n"; |
---|
234 | print "}\n\n"; |
---|
235 | } |
---|
236 | |
---|
237 | $start = 1, print "# The following groups are missing in your newsgroups file.\n" unless defined $start; |
---|
238 | $newsgroups{$group} =~ s-'-'\\''-g; |
---|
239 | print "echo '",$group, "\t", $newsgroups{$group}, "' >>", $ENV{'NEWSGROUPS'}, "\n"; |
---|
240 | } |
---|
241 | |
---|
242 | print "\n" if defined $start; |
---|
243 | |
---|
244 | print"rm -f \${TEMP} \${LOCK}\n\n" if (defined($printlock)); |
---|
245 | |
---|
246 | ######################################################################## |
---|
247 | |
---|
248 | print $ENV{'NEWSBIN'}, "/ctlinnd go Checkgroups-\$\$\n"; |
---|
249 | |
---|
250 | ######################################################################## |
---|
251 | # changegroup does not work on throttled servers. |
---|
252 | ######################################################################## |
---|
253 | |
---|
254 | if($#unmod >= 0) { |
---|
255 | print "# The following groups are incorrectly marked as moderated.\n"; |
---|
256 | foreach $group (sort @unmod) { |
---|
257 | print $ENV{'NEWSBIN'}, '/ctlinnd changegroup ', $group, " y\n"; |
---|
258 | } |
---|
259 | print "\n"; |
---|
260 | } |
---|
261 | undef @unmod; |
---|
262 | |
---|
263 | if($#mod >= 0) { |
---|
264 | print "# The following groups are incorrectly marked as unmoderated.\n"; |
---|
265 | foreach $group (sort @mod) { |
---|
266 | print $ENV{'NEWSBIN'}, '/ctlinnd changegroup ', $group, " m\n"; |
---|
267 | } |
---|
268 | print "\n"; |
---|
269 | } |
---|
270 | undef @mod; |
---|
271 | |
---|
272 | print "exit\n# end of script\n"; |
---|