1 | #!/usr/local/bin/perl |
---|
2 | # |
---|
3 | # mkngfile - make a newsgroup description file from multiple sources |
---|
4 | # |
---|
5 | # Jeremy Nixon <jeremy@exit109.com> |
---|
6 | # $Id: mkngfile,v 1.1 1999/04/17 09:19:25 jeremy Exp $ |
---|
7 | # |
---|
8 | # This program may be used and distributed under the same terms |
---|
9 | # as Perl itself. |
---|
10 | |
---|
11 | # This program creates a newsgroup description file, using one or |
---|
12 | # several input files containing group descriptions. The resulting |
---|
13 | # file will contain a description line for each group in your active |
---|
14 | # file. |
---|
15 | # |
---|
16 | # If the input contains multiple different descriptions for a group, |
---|
17 | # the program will prompt interactively for which one to use; or, if |
---|
18 | # the --noask option is given, one will be chosen arbitrarily. If a |
---|
19 | # group has no description, $default_desc (below) will be used. |
---|
20 | # |
---|
21 | # The output will be sent to stdout, or to the file specified with |
---|
22 | # the --output (or -o) option. |
---|
23 | # |
---|
24 | # Example - to run with your existing newsgroups file, a local copy |
---|
25 | # of the ISC newsgroups file, and a directory containing checkgroups |
---|
26 | # files with names like *.check, creating the new file as 'newfile': |
---|
27 | # mkngfile -o newfile /news/etc/newsgroups newsgroups checkgroups/*.check |
---|
28 | # |
---|
29 | # You can set the location of your active file below so you don't |
---|
30 | # have to specify it on the command line. |
---|
31 | |
---|
32 | use Getopt::Long; |
---|
33 | |
---|
34 | GetOptions (\%opt, qw(h help a=s active=s ask! o=s output=s)) || usage(); |
---|
35 | usage() if ($opt{'h'} or $opt{'help'}); |
---|
36 | usage('No input files specified.') unless (scalar @ARGV > 0); |
---|
37 | |
---|
38 | # If a group has no description, use this. |
---|
39 | $default_desc = '???'; |
---|
40 | |
---|
41 | # Default to asking which of multiple descriptions to use. |
---|
42 | # Comment this out if you want the default to be not to ask. |
---|
43 | $opt{'ask'} = 1 unless (defined $opt{'ask'}); |
---|
44 | |
---|
45 | # Default to system active file; you may want to change this. |
---|
46 | $active_file = $opt{'active'} || $opt{'a'} || '/news/etc/active'; |
---|
47 | usage('No active file.') unless (-r $active_file); |
---|
48 | |
---|
49 | $output_file = $opt{'output'} || $opt{'o'} || undef; |
---|
50 | |
---|
51 | # Read in the active file and create a hash. |
---|
52 | open (F, "<$active_file") || die "Can't open $active: $!\n"; |
---|
53 | %active = map { (split /\s+/, $_)[0,3] } <F>; |
---|
54 | close F; |
---|
55 | |
---|
56 | # Read in all the files and create a hash. |
---|
57 | %groups = (); |
---|
58 | while (defined ($file = shift @ARGV)) { |
---|
59 | |
---|
60 | unless (open (F, "<$file")) { |
---|
61 | print STDERR "Can't open $file: $!\n"; |
---|
62 | next; |
---|
63 | } |
---|
64 | while (defined ($line = <F>)) { |
---|
65 | chomp $line; |
---|
66 | ($group,$desc) = split /\s+/, $line, 2; |
---|
67 | $desc =~ s/\(Moderated\)//gi; |
---|
68 | $desc =~ s/^\s+//; |
---|
69 | $desc =~ s/\s+$//; |
---|
70 | next if ($desc =~ /^\s*$/ or $desc =~ /^\?+$/ or $desc =~ /no description/i); |
---|
71 | $groups{$group}{$desc} = 1; |
---|
72 | } |
---|
73 | close F; |
---|
74 | } |
---|
75 | |
---|
76 | # Go through the active file and find each group's description. |
---|
77 | @descriptions = (); |
---|
78 | foreach $group (sort keys %active) { |
---|
79 | $desc = pick_description ($group); |
---|
80 | push @descriptions, "$group\t$desc"; |
---|
81 | } |
---|
82 | |
---|
83 | # If we have an output file, open it; otherwise STDOUT is used. |
---|
84 | if ($output_file) { |
---|
85 | open (OUT, ">$output_file") or die "Can't open $output_file: $!\n"; |
---|
86 | open (STDOUT, ">&OUT") or die "Can't redirect stdout: $!\n"; |
---|
87 | } |
---|
88 | |
---|
89 | # Print the new file. |
---|
90 | map { print "$_\n" } @descriptions; |
---|
91 | |
---|
92 | close OUT if ($output_file); |
---|
93 | |
---|
94 | sub pick_description { |
---|
95 | # Given a group, return the description. |
---|
96 | # If we have more than one description for a group, we ask the |
---|
97 | # user which one to use, or just pick one if --noask is specified. |
---|
98 | # If we have no description for a group, use $default_desc. |
---|
99 | # If the group is moderated, append '(Moderated)' to the description. |
---|
100 | |
---|
101 | my ($description,$n,$c); |
---|
102 | my $ng = shift; |
---|
103 | my @descs = sort keys %{$groups{$ng}}; |
---|
104 | |
---|
105 | if (scalar @descs < 1) { |
---|
106 | $description = $default_desc; |
---|
107 | } elsif (scalar @descs == 1) { |
---|
108 | $description = $descs[0]; |
---|
109 | } else { |
---|
110 | if ($opt{'ask'}) { |
---|
111 | |
---|
112 | print STDERR "$ng - choose description:\n"; |
---|
113 | map { print STDERR " ". ++$n .". $_\n" } @descs; |
---|
114 | until ($c > 0 and $c <= scalar @descs) { |
---|
115 | print STDERR "> "; |
---|
116 | $c = <STDIN>; |
---|
117 | chomp $c; |
---|
118 | } |
---|
119 | $description = $descs[--$c]; |
---|
120 | |
---|
121 | } else { |
---|
122 | $description = $descs[0]; |
---|
123 | } |
---|
124 | } |
---|
125 | $description .= ' (Moderated)' if ($active{$ng} =~ /^m/i); |
---|
126 | |
---|
127 | return $description; |
---|
128 | } |
---|
129 | |
---|
130 | sub usage { |
---|
131 | my $message = shift; |
---|
132 | print STDERR "$message\n" if ($message); |
---|
133 | |
---|
134 | print STDERR "\nusage:\n"; |
---|
135 | print STDERR "mkngfile [options] file [file...]\n"; |
---|
136 | print STDERR " -h, --help display this message\n"; |
---|
137 | print STDERR " -a, --active path to active file\n"; |
---|
138 | print STDERR " -o, --output output file to use instead of stdout\n"; |
---|
139 | print STDERR " --ask ask which of multiple descriptions to use (default)\n"; |
---|
140 | print STDERR " --noask don't ask, just pick one\n"; |
---|
141 | print STDERR "\n"; |
---|
142 | |
---|
143 | exit 1; |
---|
144 | } |
---|