2 eval "exec perl -S $0 $*"
3 if $running_under_some_shell;
5 # $Id: patsend.SH,v 3.0.1.6 1995/09/25 09:22:02 ram Exp $
7 # Copyright (c) 1991-1993, Raphael Manfredi
9 # You may redistribute only under the terms of the Artistic Licence,
10 # as specified in the README file that comes with the distribution.
11 # You may reuse parts of this distribution only within the terms of
12 # that same Artistic Licence; a copy of which may be found at the root
13 # of the source tree for dist 3.0.
15 # Original Author: Larry Wall <lwall@netlabs.com>
17 # $Log: patsend.SH,v $
18 # Revision 3.0.1.6 1995/09/25 09:22:02 ram
19 # patch59: new -i option to add more instructions for end-users
21 # Revision 3.0.1.5 1994/01/24 14:32:46 ram
22 # patch16: now prefix error messages with program's name
23 # patch16: don't feed mailer with more than 50 addresses at a time
24 # patch16: added ~/.dist_profile awareness
26 # Revision 3.0.1.4 1993/08/25 14:08:01 ram
27 # patch6: now asks for recipient list edition by default
28 # patch6: new -q option to suppress that
30 # Revision 3.0.1.3 1993/08/24 12:21:59 ram
31 # patch3: new -u option
32 # patch3: added Precedence and X-Mailer headers in mail message
33 # patch3: added ~name expansion for orgname
35 # Revision 3.0.1.2 1993/08/19 07:10:19 ram
36 # patch3: was not correctly writing the To: header field
38 # Revision 3.0.1.1 1993/08/19 06:42:42 ram
39 # patch1: leading config.sh searching was not aborting properly
41 # Revision 3.0 1993/08/18 12:10:49 ram
42 # Baseline for dist 3.0 netwide release.
45 $orgname='Illuminati';
46 $mailer='/usr/sbin/sendmail';
50 $progname = &profile; # Read ~/.dist_profile
52 &usage unless &Getopts("hiquV");
55 print STDERR "$progname $version PL$patchlevel\n";
61 chdir '..' if -d '../bugs';
66 $orgname = &tilda_expand($orgname);
67 chop($orgname = `cat $orgname`) if $orgname =~ m|^/|;
70 if (/^(patch)?[1-9][\d,-]*$/) {
77 $dest = join(' ',@dest);
78 $dest .= " $recipients" if $opt_u;
81 # Offer to edit the address list unless -q
83 select((select(STDOUT), $| = 1)[0]);
84 print "Do you wish to edit the address list? [y] ";
86 unless ($ans =~ /^n/i) {
87 @to = split(' ', $dest);
89 $dest = join(' ', @to);
93 $to = join(', ', split(' ', $dest));
96 open(PL,"patchlevel.h") || die "$progname: can't open patchlevel.h: $!\n";
98 $maxnum = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/;
101 die "$progname: malformed patchlevel.h file.\n" if $maxnum eq '';
104 @patseq = &patseq($maxnum);
105 $lastpat = pop(@patseq);
106 $argv = &rangeargs("$lastpat-$maxnum");
108 $argv = &rangeargs(@ARGV);
111 @ARGV = split(' ',$argv);
115 print STDERR "$progname: no patches specified.\n";
118 print "$progname: sending $package $baserev patches $argv to $dest...\n";
120 print "$progname: sending $package $baserev patch $argv to $dest...\n";
123 chdir 'bugs' || die "$progname: can't cd to bugs: $!\n";
127 $opt = '-odq' if $mailer =~ /sendmail/;
132 # I hate broken mailers! Bust it up into smaller groups of people...
133 @dest = split(' ', $dest);
134 while (@smalldest = splice(@dest, 0, 50)) {
135 $to = join(', ', @smalldest); # Sensible To: for sendmail
136 $smalldest = join(' ', @smalldest);
138 open(MAILER, "|$mailer $opt $smalldest") ||
139 die "$progname: can't fork $mailer: $!\n";
142 Subject: $package $baserev patch #$patnum
144 X-Mailer: dist [version $version PL$patchlevel]
145 Organization: $orgname
149 "$package version $baserev has been recently upgraded with the following patch,
150 which is being mailed directly to you as you requested when running Configure.
152 If you are not interested in having future patches mailed directly to you,
153 please send me the following mail:
156 \@SH package - $package $baserev
158 -- $progname speaking for $maintname <$maintloc>.
160 " if ($opt_i || $opt_u);
162 "[The latest patch for $package version $baserev is #$maxnum.]
165 open(PATCH,"patch$patnum") ||
166 die "$progname: can't open patch$patnum: $!\n";
172 die "$progname: could not mail patch$patnum.\n" if $?;
178 Usage: $progname [-hiquV] [patchlist] [recipients]
179 -h : print this message and exit
180 -i : include information on how to stop receiving future patches
181 -q : quick mode, do not offer to edit recipient list
182 -u : add all to-be-mailed users
183 -V : print version number and exit
189 if (! -f '.package') {
192 -f '../../.package' ||
193 -f '../../../.package' ||
194 -f '../../../../.package'
196 die "Run in top level directory only.\n";
198 die "No .package file! Run packinit.\n";
201 open(PACKAGE,'.package');
205 if (($var,$val) = /^\s*(\w+)=(.*)/) {
206 $val = "\"$val\"" unless $val =~ /^['"]/;
207 eval "\$$var = $val;";
216 open(PL,"patchlevel.h") || die "Can't open patchlevel.h\n";
218 $maxspec = $1 if /^#define\s+PATCHLEVEL\s+(\d+)/;
221 die "Malformed patchlevel.h file.\n" if $maxspec eq '';
229 } elsif (s/^-(\d*)//) {
231 if ($max == 0 && $maxspec) {
238 for ($i = $min; $i <= $max; ++$i) {
247 return unless open(USERS, 'users');
249 local($status, $name, $pl);
252 chop if /\n$/; # Emacs may leave final line without \n
253 ($status, $pl, $name) = split;
254 # Handle oldstyle two-field user file format (PL13 and before)
255 $name = $pl unless defined $name;
256 if ($status eq 'M') {
257 $recipients = $recipients ? "$recipients $name" : $name;
258 } elsif ($status eq 'N') {
259 $notify = $notify ? "$notify $name" : $name;
265 # Compute patch sequence by scanning the bugs directory and looking for
266 # .logs and/or .mods files to determine what was the last issued patch series.
268 local($cur) = @_; # Current patch level
269 local(@seq); # Issued patch sequence
271 for ($i = 1; $i <= $cur; $i++) {
272 push(@seq, $i) if -f "bugs/.logs$i" || -f "bugs/.mods$i";
277 # Perform ~name expansion ala ksh...
278 # (banish csh from your vocabulary ;-)
281 return $path unless $path =~ /^~/;
282 $path =~ s:^~([^/]+):(getpwnam($1))[$[+7]:e; # ~name
283 $path =~ s:^~:$ENV{'HOME'} || (getpwuid($<))[$[+7]:e; # ~
287 # Compute suitable editor name
289 local($editor) = $ENV{'VISUAL'};
290 $editor = $ENV{'EDITOR'} unless $editor;
291 $editor = $defeditor unless $editor;
292 $editor = 'vi' unless $editor;
296 # Allow user to inplace-edit a list of items held in an array
299 local($tmp) = "/tmp/dist.$$";
300 local($editor) = &geteditor;
301 open(TMP, ">$tmp") || die "Can't create $tmp: $!\n";
302 foreach $item (@list) {
303 print TMP $item, "\n";
306 system "$editor $tmp";
307 open(TMP, "$tmp") || die "Can't reopen $tmp: $!\n";
313 # Set up profile components into %Profile, add any profile-supplied options
314 # into @ARGV and return the command invocation name.
316 local($profile) = &tilda_expand($ENV{'DIST'} || '~/.dist_profile');
317 local($me) = $0; # Command name
318 $me =~ s|.*/(.*)|$1|; # Keep only base name
319 return $me unless -s $profile;
320 local(*PROFILE); # Local file descriptor
321 local($options) = ''; # Options we get back from profile
322 unless (open(PROFILE, $profile)) {
323 warn "$me: cannot open $profile: $!\n";
329 next if /^\s*#/; # Skip comments
331 if (s/^$me://o) { # progname: options
333 $options .= $_; # Merge options if more than one line
335 elsif (s/^$me-([^:]+)://o) { # progname-component: value
338 s/^\s+//; # Trim leading and trailing spaces
340 $Profile{$component} = $_;
344 return unless $options;
345 require 'shellwords.pl';
347 eval '@opts = &shellwords($options)'; # Protect against mismatched quotes
348 unshift(@ARGV, @opts);
349 return $me; # Return our invocation name