1;# $Id$ 2;# 3;# Copyright (c) 1990-2006, Raphael Manfredi 4;# 5;# You may redistribute only under the terms of the Artistic License, 6;# as specified in the README file that comes with the distribution. 7;# You may reuse parts of this distribution only within the terms of 8;# that same Artistic License; a copy of which may be found at the root 9;# of the source tree for mailagent 3.0. 10;# 11;# $Log: sendfile.pl,v $ 12;# Revision 3.0.1.3 1995/02/16 14:36:59 ram 13;# patch32: indentation fix 14;# 15;# Revision 3.0.1.2 1994/10/10 10:25:40 ram 16;# patch19: added various escapes in strings for perl5 support 17;# 18;# Revision 3.0.1.1 1994/10/04 17:55:43 ram 19;# patch17: now uses the email config parameter to send messages to user 20;# 21;# Revision 3.0 1993/11/29 13:49:16 ram 22;# Baseline for mailagent 3.0 netwide release. 23;# 24;# 25;# This file contains two subroutines: 26;# - sendfile, sends a set of files 27;# - abort, called when something got wrong 28;# 29;# A routine clean_tmp must be defined in the program, for removing 30;# possible temporary files in case abort is called. 31;# 32# Send a set of files 33sub sendfile { 34 local($dest, $cf'tmpdir, $pack, $subject) = @_; 35 &add_log("sending dir $cf'tmpdir to $dest, mode $pack") if $loglvl > 9; 36 37 # A little help message 38 local($mail_help) = "Detailed intructions can be obtained by: 39 40 Subject: Command 41 \@SH mailhelp $dest"; 42 43 # Go to tmpdir where files are stored 44 chdir $cf'tmpdir || &abort("NO TMP DIRECTORY"); 45 46 # Build a list of files to send 47 local($list) = ""; # List of plain files 48 local($dlist) = ""; # List with directories (for makekit) 49 local($nbyte) = 0; 50 local($nsend) = 0; 51 open(FIND, "find . -print |") || &abort("CANNOT RUN FIND"); 52 while (<FIND>) { 53 chop; 54 next if $_ eq '.'; # Skip current directory `.' 55 s|^\./||; 56 $dlist .= $_ . " "; # Save file/dir name 57 if (-f $_) { # If plain file 58 $list .= $_ . " "; # Save plain file 59 $nsend++; # One more file to send 60 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, 61 $blksize,$blocks) = stat($_); 62 $nbyte += $size; # Update total size 63 } 64 } 65 close FIND; 66 67 &abort("NO FILE TO SEND") unless $nsend; 68 if ($nsend > 1) { 69 &add_log("$nsend files to pack ($nbyte bytes)") if $loglvl > 9; 70 } else { 71 &add_log("1 file to pack ($nbyte bytes)") if $loglvl > 9; 72 } 73 74 # Pack files 75 if ($pack =~ /kit/) { 76 system "kit -n Part $list" || &abort("CANNOT KIT FILES"); 77 $packed = "kit"; 78 } elsif ($pack =~ /shar/) { 79 # Create a manifest, so that we can easily run maniscan 80 # Leave a PACKNOTES file with non-zero length if problems. 81 local($mani) = $dlist; 82 $mani =~ s/ /\n/g; 83 local($packlist) = "pack.$$"; # Pack list used as manifest 84 if (open(PACKLIST, ">$packlist")) { 85 print PACKLIST $mani; 86 close PACKLIST; 87 system 'maniscan', "-i$packlist", 88 "-o$packlist", '-w0', '-n', '-lPACKNOTES'; 89 &add_log("ERROR maniscan returned non-zero status") 90 if $loglvl > 5 && $?; 91 if (-s 'PACKNOTES') { # Files split or uu-encoded 92 system 'makekit', "-i$packlist", '-t', 93 "Now run 'sh PACKNOTES'." || &abort("CANNOT SHAR FILES"); 94 } else { 95 system 'makekit', "-i$packlist" || &abort("CANNOT SHAR FILES"); 96 } 97 } else { 98 &add_log("ERROR cannot create packlist") if $loglvl > 5; 99 system "makekit $dlist" || &abort("CANNOT SHAR FILES"); 100 } 101 $packed = "shar"; 102 } else { 103 if ($nbyte > $cf'maxsize) { # Defined in ~/.mailagent 104 system "kit -M -n Part $list" || &abort("CANNOT KIT FILES"); 105 $packed = "minikit"; # The minikit is included 106 } else { 107 # Try with makekit first 108 if (system "makekit $dlist") { # If failed 109 system "kit -M -n Part $list" || &abort("CANNOT KIT FILES"); 110 $packed = "minikit"; # The minikit is included 111 } else { 112 $packed = "shar"; 113 } 114 } 115 } 116 117 # How many parts are there ? 118 @parts = <Part*>; 119 $npart = $#parts + 1; # Number of parts made 120 &abort("NO PART TO SEND -- $packed failed") unless $npart; 121 if ($npart > 1) { 122 &add_log("$npart $packed parts to send") if $loglvl > 19; 123 } else { 124 &add_log("$npart $packed part to send") if $loglvl > 19; 125 } 126 127 # Now send the parts 128 $nbyte = 0; # How many bytes do we send ? 129 $part_num = 0; 130 $signal=""; # To signal parts number if more than 1 131 local($partsent) = 0; # Number of parts actually sent 132 local($bytesent) = 0; # Amount of bytes actually sent 133 foreach $part (@parts) { 134 ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime, 135 $blksize,$blocks) = stat($part); 136 $nbyte += $size; # Update total size 137 138 &add_log("dealing with $part ($size bytes)") if $loglvl > 19; 139 140 # See if we need to signal other parts 141 $part_num++; # Update part number 142 if ($npart > 1) { 143 $signal=" (Part $part_num/$npart)"; 144 } 145 146 # Send part 147 open(MAILER, "|$cf'sendmail $cf'mailopt $dest"); 148 print MAILER 149"To: $dest 150Subject: $subject$signal 151Precedence: bulk 152X-Mailer: mailagent [version $mversion-$revision] 153 154Here is the answer to your request: 155 156 $fullcmd 157 158 159"; 160 if ($packed eq 'minikit') { # Kit with minikit included 161 print MAILER 162"This is a kit file. It will be simpler to unkit it if you own the kit 163package (latest patchlevel), but you can use the minikit provided with 164this set of file (please see instructions provided by kit itself at the 165head of each part). If you wish to get kit, send me the following mail: 166 167"; 168 } elsif ($packed eq 'kit') { # Plain kit files 169 print MAILER 170"This is a kit file. You need the kit package (latest patchlevel) to 171unkit it. If you do not have kit, send me the following mail: 172 173"; 174 } 175 if ($packed =~ /kit/) { # Kit parts 176 print MAILER 177" Subject: Command 178 \@PACK shar 179 \@SH maildist $dest kit - 180 181and you will get the latest release of kit as shell archives. 182 183$mail_help 184 185"; 186 # Repeat instructions which should be provided by kit anyway 187 if ($npart > 1) { 188 print MAILER 189"Unkit: Save this mail into a file, e.g. \"foo$part_num\" and wait until 190 you have received the $npart parts. Then, do \"unkit foo*\". To see 191 what will be extracted, you may wish to do \"unkit -l foo*\" before. 192"; 193 } else { 194 print MAILER 195"Unkit: Save this mail into a file, e.g. \"foo\". Then do \"unkit foo\". To see 196 what will be extracted, you may wish to do \"unkit -l foo\" before. 197"; 198 } 199 # If we used the minikit, signal where instruction may be found 200 if ($packed eq 'minikit') { 201 print MAILER 202" This kit archive also contains a minikit which will enable you to 203 extract the files even if you do not have kit. Please follow the 204 instructions kit has provided for you at the head of each part. Should 205 the minikit prove itself useless, you may wish to get kit. 206"; 207 } 208 } else { # Shar parts 209 print MAILER 210"This is a shar file. It will be simpler to unshar it if you own the Rich Salz's 211cshar package. If you do not have it, send me the following mail: 212 213 Subject: Command 214 \@PACK shar 215 \@SH maildist $dest cshar 3.0 216 217and you will get cshar as shell archives. 218 219$mail_help 220 221"; 222 if (-s 'PACKNOTES') { # Problems detected by maniscan 223 print MAILER 224" 225Warning: 226 Some minor problems were encountered during the building of the 227 shell archives. Perhaps a big file has been split, a binary has been 228 uu-encoded, or some lines were too long. Once you have unpacked the 229 whole distribution, see file PACKNOTES for more information. You can 230 run it through sh by typing 'sh PACKNOTES' to restore possible splited 231 or encoded files. 232 233"; 234 } 235 if ($npart > 1) { 236 print MAILER 237"Unshar: Save this mail into a file, e.g. \"foo$part_num\" and wait until 238 you have received the $npart parts. Then, do \"unshar -n foo*\". If you 239 do not own \"unshar\", edit the $npart files and remove the mail header 240 by hand before feeding into sh. 241"; 242 } else { 243 print MAILER 244"Unshar: Save this mail into a file, e.g. \"foo\". Then do \"unshar -n foo\". If 245 you do not own \"unshar\", edit the file and remove the mail header by 246 hand before feeding into sh. 247"; 248 } 249 } 250 print MAILER 251" 252-- $prog_name speaking for $cf'user 253 254 255"; 256 open(PART, $part) || &abort("CANNOT OPEN $part"); 257 while (<PART>) { 258 print MAILER; 259 } 260 close PART; 261 close MAILER; 262 if ($?) { 263 &add_log("ERROR couldn't send $size bytes to $dest") 264 if $loglvl > 1; 265 } else { 266 &add_log("SENT $size bytes to $dest") if $loglvl > 2; 267 $partsent++; 268 $bytesent += $size; 269 } 270 } 271 272 # Prepare log message 273 local($partof) = ""; 274 local($byteof) = ""; 275 local($part); 276 local($byte); 277 if ($partsent > 1) { 278 $part = "parts"; 279 } else { 280 $part = "part"; 281 } 282 if ($bytesent > 1) { 283 $byte = "bytes"; 284 } else { 285 $byte = "byte"; 286 } 287 if ($partsent != $npart) { 288 $partof = " (of $npart)"; 289 $byteof = "/$nbyte"; 290 } 291 &add_log( 292 "SENT $partsent$partof $packed $part ($bytesent$byteof $byte) to $dest" 293 ) if $loglvl > 4; 294} 295 296# In case something got wrong 297# We call the clean_tmp routine, which must be defined in the 298# main program that will use abort. 299sub abort { 300 local($reason) = shift; # Why do we abort ? 301 local($cmd) = $fullcmd =~ /^(\S+)/; 302 open(MAILER, "|$cf'sendmail $cf'mailopt $path $cf'email"); 303 print MAILER 304"To: $path 305Subject: $cmd failed 306X-Mailer: mailagent [version $mversion-$revision] 307 308Sorry, the $prog_name command failed while sending files. 309 310Your command was: $fullcmd 311Error message I got: 312 313 >>>> $reason <<<< 314 315If $cf'name can figure out what you meant, he may answer anyway. 316 317-- $prog_name speaking for $cf'user 318"; 319 close MAILER; 320 &add_log("FAILED ($reason)") if $loglvl > 1; 321 &clean_tmp; 322 exit 0; # Scheduled error 323} 324 325