#! /usr/bin/perl -w $^W = 1; # same as -w above # (C) Copyright 2003 Rahul Dhesi, All rights reserved. # Use, copying, distribution, and modification are permitted in # accordance with the GNU General Public License. use strict; # unbuffered output is usually desired $| = 1; # $Source: /usr/local/billmax/a2i/RCS/bmlpr,v $ # $Id: bmlpr,v 1.29 2003/11/06 21:13:10 lrdroot Exp $ # # Filter printer output from BillMax. $::myname = $0; $::myname =~ s|.*/||; $::RCSHEADER = '$Source: /usr/local/billmax/a2i/RCS/bmlpr,v $' . "\n" . '$Id: bmlpr,v 1.29 2003/11/06 21:13:10 lrdroot Exp $'; my $cmtfile; # BEGIN CONFIGURATION SECTION # Define the path for the 'lpr' program here. This may be the full # path, or it may be just the program name. If using just the program # name, we define PATH so lpr can be found somewhere in it. $ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin:/sbin:/usr/local/bin'; $::LPR = 'lpr'; # default positions of sender and recipient address on printed statement, # lines down from top edge $::SENDERPOS_DEFAULT = 4; $::RECIPPOS_DEFAULT = 13; $::RECIPMARGIN_DEFAULT = 6; $::LINEPOS_DEFAULT = 21; $::BODYPOS_DEFAULT = 23; # comment file if needed # $cmtfile = undef; $cmtfile = '/var/tmp/comments.txt'; # END CONFIGURATION SECTION # suppresss perl warnings $::debug = $::opt_x = undef; $::ddebug = $::opt_X = undef; $::verbose = $::opt_v = undef; $::trace = $::opt_t = undef; $::opt_h = undef; $::opt_s = undef; $::opt_r = undef; $::opt_l = undef; $::opt_b = undef; $::opt_m = undef; $::opt_P = undef; $::opt_R = undef; $::opt_S = undef; $::opt_H = undef; $::usage = "usage: $::myname [-vtxX] [-S spos ] [-R rpos ] [ -b bpos ] [-m marg] -P printer (or -H for help)"; if (@ARGV && $ARGV[0] =~ "^-.+" ) { local($^W) = 0; # suppress annoying undef warnings require "getopts.pl"; &Getopts("vtxXhP:s:r:b:m:l:c:HR:S:Z");# Z will suppress perl warning } $::ddebug = $::opt_X; # extended debug $::debug = $::opt_x || $::ddebug; # debug $::trace = $::opt_t; $::verbose = $::debug || $::trace || $::opt_v; if ($::opt_H) { &givehelp(); exit(0); } my $senderpos = $::opt_S || $::SENDERPOS_DEFAULT; my $recippos = $::opt_R || $::RECIPPOS_DEFAULT; my $bodypos = $::opt_b || $::BODYPOS_DEFAULT; my $recipmargin = $::opt_m || $::RECIPMARGIN_DEFAULT; my $linepos = $::opt_l || $::LINEPOS_DEFAULT; ## (@ARGV < 1) && &usage_error; # lpr options if supplied to us my @lpropts = (); $::opt_s && push(@lpropts, '-s'); $::opt_h && push(@lpropts, '-h'); $::opt_r && push(@lpropts, '-r'); my $printer = $::opt_P || &usage_error; # open the real lpr program on filehandle LPR # .. in trace mode, we simply print to stdout if ($::trace) { open(LPR, ">&STDOUT") || die "$::myname: dup of STDOUT failed: $!\n"; } else { my $pid = open(LPR, "|-"); defined($pid) || die "$::myname: fork failed: $!\n"; if ($pid == 0) { # child exec($::LPR, @lpropts, '-P', $printer); die "$::myname: error: exec of $::LPR failed: $!\n"; } } # read stdin and then pipe to printer # .. and grab the account number too my $acctno = undef; # keep track of line count my $linecount = 0; # go past banner # .. look for two lines of dashes my $dashcount = 0; # count of dashed lines seen while (<>) { print LPR $_; $linecount++; /^\Q------\E/ && $dashcount++; $dashcount >= 2 && last; # seen two dashed lines } # collect sender lines my @sender; # sender address lines my $insender = 0; # whether we are in the sender lines now while (<>) { # grab account number if (! defined($acctno) && /\baccount\s+number\:\s+(\d+)\s*$/i) { $acctno = $1; $::debug && print "> found account number [$acctno]\n"; } $insender && /^\s*$/ && last; # done with sender lines /^\s*$/ && next; # skip empty line # line is non-empty, so collect it $insender = 1; # we are in the sender lines now push(@sender, $_); } $::debug && !defined($acctno) && print "> account number not found\n"; # collect recipient lines my @recipient; # recipient address lines my $inrecipient = 0; # whether we are in the recipient lines now while (<>) { $inrecipient && /^\s*$/ && last;# done with recipient lines /^\s*$/ && next; # skip empty line # line is non-empty, so collect it $inrecipient = 1; # we are in the recipient lines now push(@recipient, $_); } # we have now collected the sender and recipient lines, and have # seen one empty line just after the recipient lines. # SEND SENDER AND RECIPIENT LINES TO OUTPUT, FORMATTED FOR OUR # ENVELOPES # move down to the needed position of the sender address if ($senderpos) { while ($linecount < $senderpos) { print LPR "\n"; $linecount++; } } # print sender address for my $i (@sender) { print LPR $i; $linecount++; } # move down to the needed position of the recipient address if ($recippos) { while ($linecount < $recippos) { print LPR "\n"; $linecount++; } } # print recipient address, using any specified margin for my $i (@recipient) { if ($recipmargin) { my $t = $i; # don't change orig array in case we need it later $t =~ s/^\s+//; $t = (' ' x $recipmargin) . $t; print LPR $t; $linecount++; } else { print LPR $i; $linecount++; } } # only if -l is nonzero, specified, print a dashed line at that position if ($linepos) { while ($linecount < $linepos) { print LPR "\n"; $linecount++; } print LPR ('-' x 72), "\n"; } # print the rest, positioning it on the desired line if ($bodypos) { while ($linecount < $bodypos) { print LPR "\n"; $linecount++; } } while (<>) { print LPR $_; $linecount++; } # Add trailing info (not in use) if (0) { defined($acctno) || die "$::myname: error: account number not found\n"; print LPR "=== account number $acctno ===\n"; } # add contents of comment file if needed # .. skipping lines beginning with # # .. stopping at first line beginning with END if ($cmtfile && open(F, $cmtfile)) { while () { /^END\b/ && last; /^#/ && next; print LPR $_; $linecount++; } } # add debugging output if needed if ($::ddebug) { print LPR "=== DEBUG : ENVIRONMENT FOLLOWS ===\n"; for my $var (keys %ENV) { print LPR "$var=", $ENV{$var}, "\n"; } } # detect lpr errors close(LPR) || die "$::myname: write to LPR failed: $!\n"; sub usage_error { my($msg) = @_; if ($msg) { die "$msg\n"; } else { die "$::usage\n"; } } sub givehelp { ## require 'local/page.pl'; ## &page(< Global Options and then specify the value of \'lprpath\' as the pathname of this program. Then either adjust the default values of the constants in the CONFIGURATION SECTION of this program, or specify some or all of the values as command line arguments in the definition of \'lprpath\'. I.e., the definition of lprpath can look like either of these: /usr/local/bin/bmlpr /usr/local/bin/bmlpr -S 15 -R 25 -m 6 -l 33 -b 34 HOW TO ADJUST First adjust the -l argument (or the \$::LINEPOS_DEFAULT symbol in the source code) to get the dashed line at the right position, while keeping the other values low enough to not interfere. When correctly adjusted, you should be able to fold the statement on the dashed line and get the top portion of the printed statement to fit snugly within the envelope. The rest of the paper can be folded in any way, so long as the folded width is not too great. Then individually adjust the -S, -R, and -m values (or their defaults in the source code) to place the addresses to fit within the window(s) of your envelopes. COMMAND-LINE OPTIONS -v Be verbose. -t Trace only -- show what would be done but don\'t do it (sends everything to stdout and not to printer). -x Enable debugging -- for program maintainers. -X Enable more debugging -- for program maintainers. -S spos Position of sender address (default is $::SENDERPOS_DEFAULT). -R rpos Position of sender address (default is $::RECIPPOS_DEFAULT). -b bpos Position of body (default is $::BODYPOS_DEFAULT). -m marg Left margin, in columns, for recipient address (default is $::RECIPMARGIN_DEFAULT). -l lpos Position of dashed line for folding statement (default is $::LINEPOS_DEFAULT). -P printer The name of the printer. -r, -s, -h Passed on to lpr program. Technical support: Only if you wish to be billed for my consulting services, you may contact me directly to get help with this program. Otherwise, questions should be sent to the questions\@billmax.com mailing list, where I will reply as time permits. (This long help output should be piped through \'more\' or \'less\'.) $::RCSHEADER EOF }