home *** CD-ROM | disk | FTP | other *** search
- #!/usr/local/bin/perl
- # dorequest.pl --
- # SCCS Status : @(#)@ dorequest 3.17
- # Author : Johan Vromans
- # Created On : ***
- # Last Modified By: Johan Vromans
- # Last Modified On: Sat Jun 6 21:11:24 1992
- # Update Count : 135
- # Status : Going steady
-
- # Usage: dorequest [options] -- to run the queue
- #
- # dorequest [options] address file [ encoding [ limit [ list ] ] ]
- # -- to send a file 'by hand'.
- #
- # address : where to send the information to.
- # If left empty, no splitting is done, and the result
- # is written to stdout.
- #
- # file : the file to send.
- #
- # encoding: how to encode it: U (uuencode), B (btoa), D (Dumas uue)
- # or A (plain).
- # Default is btoa.
- #
- # limit : how many bytes per transmission.
- # Default is 32768
- #
- # parts : comma-separated list of part numbers.
- # When used, only these parts are sent.
- #
- $my_name = "dorequest";
- $my_version = "3.17";
- #
- ################ Common stuff ################
-
- $libdir = $ENV{"MSERVLIB"} || "/usr/local/lib/mserv";
- unshift (@INC, $libdir);
- require "mserv_common.pl";
-
- ################ Options handling ################
-
- &options if @ARGV > 0 && $ARGV[0] =~ /^-+[^-]+/;
- undef $mailer_delay if $opt_debug;
-
- ################ Setting up ################
-
- if ( @ARGV > 0 ) {
- &usage unless @ARGV > 1;
- local ($rcpt, $address, $request, $file, $encoding, $limit, $parts);
- ($rcpt, $file, $encoding, $limit, $parts) = @ARGV;
- $request = $file;
- $address = $rcpt;
- require "$libdir/dr_mail.pl";
- &mail_request ($rcpt, $address, $request, $file, $encoding, $limit, $parts);
- }
- else {
- &synchronize;
- &seize_queue;
- while ( @queue > 0 ) {
- local ($current_queue_entry) = &shift_queue;
- local (@arg) = split (/[ \t\n]/, $current_queue_entry);
- $current_queue_entry = join (" ", @arg);
- local ($cmd) = shift (@arg);
-
- if ( $cmd eq "M" ) {
- require "$libdir/dr_mail.pl";
- eval { &mail_request (@arg); };
- }
- elsif ( $cmd eq "U" ) {
- require "$libdir/dr_uucp.pl";
- eval { &uucp_request (@arg); };
- }
- elsif ( $cmd eq "MP" ) {
- require "$libdir/dr_pack.pl";
- eval { &pack_mail_request (@arg); };
- }
- elsif ( $cmd eq "UP" ) {
- require "$libdir/dr_pack.pl";
- eval { &pack_uucp_request (@arg); };
- }
- else {
- # This is fatal!
- &die ("Illegal request in queue: $cmd @arg");
- }
- }
- # Get rid of queue backup file.
- unlink ("$queue~");
- }
-
- exit (0);
-
- ################ Subroutines ################
-
- sub synchronize {
-
- # NOTE: It is very important to prevent multiple copies
- # of this program to run at the same time!
-
- # Proceed at your own risk here...
- return unless defined $lockfile;
-
- # Create lockfile if it does not exists.
- if ( ! -e $lockfile ) {
- open (LF, ">$lockfile");
- close (LF);
- }
-
- # Open it, and get exclusive access.
- open (LF, "+<$lockfile")
- || &die ("Cannot gain lock [$!]");
- local ($ret) = &locking (*LF, 0);
- # Exit gracefully if some other invocation has the lock.
- exit (0) if $ret == 0;
- &die ("Cannot lock lockfile [$!]") unless $ret == 1;
-
- # We keep it locked until process termination.
- }
-
- sub seize_queue {
-
- local ($queuecnt);
-
- # First, check the queue backup. This file can exists only
- # if a previous run failed to terminate normally.
- if (open (QUEUE, "$queue~")) {
- @queue = <QUEUE>; # Slurp.
- close (QUEUE);
- unlink ("$queue~")
- || &die ("Cannot unlink queue~ [$!]");
- $queuecnt = @queue;
- print STDERR ("Got $queuecnt entries from $queue~\n")
- if $opt_debug;
- }
- else {
- @queue = ();
- $queuecnt = 0;
- }
-
- # Now check the current queue. We use exclusive access to make
- # sure no other process is updating it.
- # Again, proceed at your own risk if you're not using locks.
- if (open (QUEUE, "+<$queue" )) {
- # We cannot use rename queue -> queue~, since some other process
- # may already be waiting for the queue to become free.
- # Therefore slurp + truncate it.
- if ( &locking (*QUEUE, 1) ) {
- push (@queue, <QUEUE>); # Slurp.
- truncate ($queue, 0)
- || &die ("Cannot truncate queue [$!]");
- close (QUEUE);
- }
- else {
- &die ("Cannot seize queue [$!]");
- }
- print STDERR ("Got ", @queue-$queuecnt, " entries from $queue\n")
- if $opt_debug;
- }
- # 'No queue' is a normal situation....
- }
-
- sub shift_queue {
- # Sync the memory copy of the queue to disk (in the queue backup
- # file), and extract the first entry of it.
-
- open (QUEUE, ">$queue~")
- || &die ("Cannot sync queue [$!]");
- print QUEUE @queue; # Blurb.
- close (QUEUE);
-
- # Get entry from queue and return it.
- shift (@queue);
- }
-
- sub check_file {
- local ($file, $dir) = @_;
-
- # Check if a given file still exists. Non-existent files are
- # trapped anyway, but this gives a better error message.
-
- return 1 if -r $file && ( $dir ? ( -d _ && -x _ ) : -f _ );
- &die (($dir ? "Directory" : "File") .
- " \"$file\" is no longer available");
- }
-
- ################ subroutines ################
-
- sub fnsplit {
- local ($file) = @_;
- # Normalize $file -> ($dir, $basename)
- local (@path) = split (/\/+/, $file);
- (join ("/", @path[0..$#path-1]), $path[$#path]);
- }
-
- sub system {
- local ($cmd) = (@_);
- local ($ret);
- local ($opt_nolog) = 0;
- print STDERR ("+ $cmd\n") if $opt_trace;
- $ret = system ($cmd);
- &die (sprintf ("Return 0x%x from \"$cmd\"", $ret))
- unless $ret == 0;
- $ret;
- }
-
- sub symlink {
- local ($old, $new) = @_;
- print STDERR ("+ symlink $old $new\n") if $opt_trace;
- symlink ($old, $new)
- || &die ("Cannot symlink $old to $new [$!]\n");
- }
-
- sub die {
- local ($msg) = (@_);
- local ($opt_nolog) = 0; # Will force logging
- local ($opt_debug) = 1; # Will force msg to STDERR
- &writelog ("F $msg");
- if ( defined $current_queue_entry ) {
- &writelog ("Q $current_queue_entry");
- &feedback ($current_queue_entry, $msg);
- }
- die ("Aborted\n");
- }
-
- sub writelog {
-
- # Write message to logfile, if possible, Otherwise use STDERR.
-
- local (@tm) = localtime (time);
- local ($msg) = sprintf ("%02d%02d%02d %02d:%02d %s\n",
- $tm[5], $tm[4]+1, $tm[3], $tm[2], $tm[1], $_[0]);
-
- if ( !$opt_nolog && defined $logfile && ( -w $logfile ) &&
- open (LOG, ">>" . $logfile) ) {
- if ( &locking (*LOG, 1) ) {
- seek (LOG, 0, 2);
- print LOG $msg;
- close LOG;
- return unless $opt_debug;
- }
- }
-
- print STDERR $msg;
- }
-
- sub feedback {
- local ($q, $msg) = @_;
-
- # Try to send a message to the requestor indicating
- # something went wrong.
-
- local ($type, $rcpt, @q) = split (/ /, $q);
- local ($file, $req, $method);
- if ( $type =~ /^U/ ) {
- ($req, $file) = @q[2,3];
- $method = "via UUCP to \"$q[0]\"";
- }
- else {
- ($req, $file) = @q[1,2];
- $method = "via email to \"$q[0]\"";
- }
-
- local ($cmd) = "$sendmail '" . $rcpt . "'";
-
- print STDERR ("+ |", $cmd, "\n") if $opt_trace;
-
- return unless open (MAIL, "|" . $cmd);
- print MAIL <<EOD;
- To: $rcpt
- Subject: Mail Server error
- X-Server: $my_package [$my_name $my_version]
- X-Oops: I am sorry for the inconvenience
-
- Dear user,
-
- EOD
- $message = "A mail server error has occurred while trying to transfer ".
- "\"$file\" $method in response to your request for \"$req\".";
- select (MAIL);
- $~ = "fill";
- write;
- print MAIL <<EOD;
-
- The error message was:
- $msg
-
- You may wish to resubmit your request, or consult the mail server
- maintainer.
- (He knows about the error already, no need to inform him.)
-
- EOD
- close (MAIL);
- select (STDOUT);
- }
-
- format fill =
- ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<~~
- $message
- .
-
- sub options {
- require "newgetopt.pl";
- if ( !&NGetOpt ("nomail", "keep=s",
- "debug", "trace", "help")
- || defined $opt_help ) {
- &usage;
- }
- $opt_trace |= $opt_debug;
- }
-
- sub usage {
- print STDERR <<EndOfUsage;
- $my_package [$my_name $my_version]
-
- Usage: $my_name [options] [address file [coding [size [parts]]]]
-
- Options:
- -nomail do not deliver
- -keep XXX keep temporary files, using prefix XXX (for debugging)
- -help this message
- -trace show commands
- -debug for debugging
-
- address destination for this request.
- If empty: do not split and write to STDOUT.
- file the file to send.
- coding encoding (Btoa, Uuencode, Dumas uue or Plain, def Btoa).
- size max. size per chunk, def 32K.
- parts comma-separated list of parts to re-send.
- If omitted: send all parts
- EndOfUsage
- exit (!defined $opt_help);
- }
-