#!/bin/sh # LPR2 -- Utility to print postscript document on both sides. VERSION='1.2l' COPYRIGHT=\ 'Copyright (c) 1994,,,,1998 François-René Bân Rideau DDa(.ng-Vu~ "Faré" License: GPL+restrictions(SmileWare+CharityWare) ' ### BEGIN_COMMENTS # Hint: search string "INV" (for INVOCATION) to find the list of options. # Using vi or less, that's command "/INV". Your mileage may vary. ####################### LEGAL STUFF, LICENSE, ET AL. ######################### # COPYLEFT NOTICE: # This is not public domain, but copyrighted free software # with small license restrictions. : see $COPYRIGHT # LICENSE AGREEMENT: # This program is distributed under the *modified* terms of the # GNU General Public License (any official version you can find). # Particularly, # 0) You are mostly free to use and redistribute this program. # 1) there is absolutely NO WARRANTY about what effect it can have # on your software or hardware. # 2) you may strip off any comment or useless characters and statements # from this file, but only for personal use: you shall not distribute # a modified or stripped version. # 3) In *addition* to restrictions imposed on you by the GPL, # I include SmileWare and CharityWare restrictions, as defined below, # that are recursively valid for you and anyone you'll redistribute # the software to. Please do not use LPR2 without complying to them. # SMILEWARE+CHARITYWARE # Here are my SmileWare modifications to the GPL. Abide by them... # # This program is SmileWare: # 1) if you use this program several times, if you modify it, or enhance it # in any way, you should send me a note, letter, postcard, or even just an # e-mail. This note should contain your feedback about your using this # program, suggestions about improvements, enhancements, etc, if you have any. # But even if you don't, a note/card/etc with just some kind words or a smiley # is welcome. # # This program is CharityWare: # 2) if you use this program regularly, or reuse it more than three months # after you originally used it, I morally bind you to pay for it. # The exact amount you pay is up to you, but it shouldn't be less than one # hundredth of what a typical commercial program costs around your place, # which should be at least approximately half a US dollar; # what you pay should also not less than the expenses # that will incur to you for paying. # Once you determined how much to pay, you should do one of the following # with that money: # a) give it all to the next beggar you meet # (ain't there one just round the corner ?); # if you think it's too much money for you to give him, well, # firstly, you're paying for this program, so consider it's *me* giving your # money to the beggar, and second, it will be fun to you to look at his # reaction. # b) if you really don't want to give this money to this beggar or any other # near where you live, or if there's no beggar where you live, # send your money to any charitable or ecological organization # you *know* to be honest. # c) if you won't give to a beggar, and don't trust any charitable or # ecological organization, then send it to me, and I'll do it myself. # So that this charity be officially a payment for lpr2, you should # explicitly tell whoever you give that this is an lpr2-induced donation, # even though the person will most likely not understand. It would be nice # if you also warn me when you fulfill this part of the user license, # but that's not compulsory. # Of course, this should not be part of your usual charity behavior, # but *extra* charity you're being involved into. # # My addresses are at the end of these comments. # (search for string "ADDRESS" or "AUTHOR") # # This program is open source software: # should someone else decide to take over maintenance of this program # (for instance, because I am unable or unwilling to do so), or wishes # to improve, adapt or modify it, he may do it under the unmodified # and unrestricted GPL, version 2.0 or later. ########################### DESCRIPTION AND HELP ############################# # WHAT LPR2 IS MEANT TO BE: # To save paper, and lighten you backpack, without lightening your purse by # buying printers that already print documents on both sides, do use this # program to print double sided documents. # Not throwing away paper is good for just everyone throughout the world. # Stop the spillage, help save the world, use LPR2 ! # Enhanced version 1.2 now works with *all* documents I've tried it with !!! # WHAT LPR2 IS *NOT* MEANT TO BE: # This program is NOT a full-featured program # for manipulating postscript documents either. # free software (mpage, psutil/pstools), # and commercial software (from Adobe or whoever) will do that for you. # However, I tried all the free utilities I could find, # and for the majority of the documents I've tried to manipulate, # that I got from throughout the Internet # (papers that were written using various software from various platforms), # none of these utilities would work properly: # sometimes it wouldn't work at all, or it would mirror the pages, # lose font information, or choke in the middle of the document # (typically right at the page where some external postscript documents # was imported into the original paper: figure, picture, etc). # I haven't tried any commercial software, # but I doubt they would be any better. # LPR2 won't replace the multipage "n-up" feature, # available from the previous utilities (well I feel it could be done, # but not without a careful study of postscript; # I feel that a postscript decompiler would then be much more useful); # it won't provide all the bells and whistles they have; # but at least it will provide a page selection mechanism # that actually works on all reasonable documents: # LPR2 has never failed on any published document it has been tried with yet # (however, it would be trivial to write some postscript document/program # specifically for LPR2 to fail at). # This program is NOT a "standalone" postscript interpreter either. # You still need another PostScript interpreter to get it to work. The # interpreter is typically just your PostScript printer, or GhostScript, # or whatever. If you have a non-PostScript printer, the Printing-HOWTO # (somewhere on all Linux sites) will explain you how to set up "lpr" to # work with PostScript documents anyway, using GhostScript as the interpreter # (that's free software). # WHERE TO FIND THE LATEST VERSION # The latest version should be available by anonymous ftp: # * on my WWW page, "http://www.tunes.org/~fare/" # subdocument "files/lpr2.gz" # # Every once in a while, I release a version of LPR2 # on the standard Linux archive... # * on "ftp://sunsite.unc.edu/pub/Linux/" and mirror linux sites, # in subdirectory "system/printing/", files "lpr2*" # # * if you know any site where people would look for such a program, # please tell me, so I can upload and spread this utility. # HOW IT WORKS: # The shell part is only a wrapper to accept all the different options. # The core of the program (the shell function redefshowpage) # prepends some PostScript code to the file to print, # that redefines "showpage" so that it will print every other page. # According to the new showpage skipping the # first page or not, we obtain one document for recto sides, and one another # for verso sides. We then have to print it all... # Note that as the program redefines *global* variables, it cannot be # recursively called. But as the page selection function is programmable, # such use isn't needed. If you know how to reliably use local variables # in postscript, please tell me. # There should not be any clash with variables from the postscript file to # be printed; if however there was one, you can still modify those names in # the postscript part of LPR2. # Because all that's done is prepending a header, # I've successfully used LPR2-generated headers # to achieve duplex printing from a DOS machine (without /bin/sh) # driving a simplex printer. # HOW WELL THE PROGRAM SHOULD BEHAVE: # This program works very well for me. # - you need a shell that supports shell functions (SYSV or SunOS shells do, # while Ultrix shell doesn't). If yours doesn't work, try getting ksh, bash or # better even, *zsh* (use option -fy for sh emulation) from the net. # - because we mostly use plain Bourne shell, we can't deal with spaces # or NUL characters in filenames. Beware! # - alternatively, if you have no /bin/sh compatible shell, # you can manually generate the header that you'd like # (or generate it on another machine), # and use that header by prepending it to the code # you're sending to your postscript device # e.g. under DOS, "copy /b header.ps + foo.ps prn" # I always have even.ps (output of lpr2 -e /dev/null) # and odd.ps (output of lpr2 -o /dev/null) handy # on this printer-driving DOS PC. # - The program should work on any well-behaved PostScript document # (i.e. the kind of documents standard applications produce), # but is reported to fail when used in combination # with some dirty Postscript utilities. # mpage by Mark P. Hahn 1988 is such dirty program that fails :( :(. # Happily, recent versions of mpage already support page selection, # so *when mpage works* (not often), LPR2 is not needed anyway. # - You should be able to refeed the printer with its first output, # and of course, be sure that no one else will use the printer # while you are feeding the printer # with the output for the verso side of the documents. # - sometimes, some printers don't like to print on sheets # that have just been printed and are still hot. # Just wait a few minutes/seconds before you refeed the sheets. # - If your printer output pages in the reverse order, # you're in for a double session of reordering pages :( :( :( # PROGRAM HISTORY: # +%Y%m $VERSION # 1993-1994: I suffer from having to waste half of my paper # with simplex printing # 199406: I'm seriously looking for duplex printing utilities # 19940? 0.0: just postcript code manually prepended to a document. # developped with ghostscript. # 19940? 0.1: the same, but working (with the discovery of erasepage) # 199407 1.0: a script that doesn't even work (I'm ashamed of that)-8 # 199407 1.1: the same, but bugs fixed: # - cat <<"END" was used instead of cat<). # Help options are supported. # 199408 1.1c: bugs corrected: quotes not closed >8 ; # run-time message modified # 1994?? 1.1d: added arbitrary page selection through -c (hackish) # 199501 1.2: used the ps2ppm PageCount trick using strings to escape # save/restore sequences. LPR2 now works with all files # I've tried it with ! # 199501 1.2b: Just understood why ps2ppm added 1000000 to page count. # LPR2 now works after page 9 :) # 1995?? 1.2c: added nicer page selection: page can be named as p... # 199508 1.2d: merged feedback from Rainer Blome (rainer@physik3.gwgd.de): # - removed the -P,--print "I changed my mind. Do print" option # because it conflicted with a common printer option. # - extended the description of how to reinsert paper. # 199508 1.2e: - added the -p option # - replaced the default behavior (print) by printing to stdout # if any option is present. Restored option -P, with options # -z and -Z to select printing command and default option # behavior to "unknown option" instead of passing it blindly # to lpr. # - added SmileWare restrictions to the GPL (see above). # - released lpr2 to sunsite # 199604 1.2f: - minor bug fixes in code and documentation # 199610 1.2g: - made it compatible again with the lame /bin/sh from SunOS # 199610 1.2h: - added documentation about using LPR2 with a shared printer # 199701 1.2i: - corrected minor "bugs" in the documentation. # - added some dates in this HISTORY # - added a CREDITS entry # - added code for self-release -- fun administrative stuff # (auto-generate .lsm entry with right sizes) # 199702 1.2j: - minor changes (mostly administrative). # 199702 1.2k: - added option -A; bugfix: s/\$2/\$1/ in -z and -Z option # 199808 1.2l: - clarified license, address change. # TO DO: # - intercept showsheet, restore, not just showpage (?) # - if we know some upper bound to the last page to be printed, put some # "end execution" Postscript instruction for when this page is reached; # of course, I should first find how this can in done in PostScript :) # - Instead of continuing this lame LPR2 program, I should most certainly # take some good program like mpage or the psutil package, and fix them # so they work on documents for which LPR2 is currently needed. # - if the latter is impossible, at least, steal from these programs code # to do n-up, so LPR2 has their full functionality. # - in this last case, someday, redefine just everything, not just showpage # ;->, thus having the ultimate Postscript meta-program. # - perhaps one day, write a postscript source manipulator and partial # evaluator. # - include an "autosplit" feature someday, # to split lpr2 into documentation and stripped source file ;-) ############################ USAGE INSTRUCTIONS ############################## # INSTALLATION PROCEDURE: # - mv lpr2*.gz lpr2.gz # - gunzip lpr2 # - chmod 0755 lpr2 # - mv lpr2 /somewhere_in_my_PATH/bin/ # - edit the file to customize if need be (look for !!!! marks): # the LPR= line should contain the name of a command or function that # will print its PostScript standard input. I put "lpr" as the default. # Full path might help in some cases. # - Enjoy ! # USAGE: # To print document "doc.ps", print odd pages on one side and even pages on # the other. # # My HP LaserJet 4ML printer issues pages in the "right" order, # i.e. the page on top exits on top. # I also have to feed paper with verso (back) upward, # and top of sheet near me. # Thus, I have to print even pages first, then odd pages. # That's what the default behaviour is. # # Rainer Blome (rainer@physik3.gwdg.de) says: ## My default `PostScript' printer, an HP LJ III, does emit pages in the ## `right' order (small page numbers on top), but does not feed verso. a ## stack of paper exits the printer exactly the same configuration as it has ## been put in the paper cassette. ## To get the desired result, however, i need the pages in this order, yes, ## but the empty side has to be in the position that will be printed on. the ## HP IV does that automatically, each page is reversed on every printing. ## Thus, `print on reverse side' with `emit in right order' is OK, as is ## `print on topside' with `emit in wrong order'. other combinations require ## reordering/reversal by hand. # # If you need some other behaviour, please tell me or correct it and send # me feedback. # # Beware that there may be one odd page more than even pages. # Sheets must be fed with verso on top. # Default option (--all) does it. # # Thus, the usage is: feed blank sheets to the printer, # mark one corner with a pencil # to see how you will have to feed sheets again to print the other side. # Then, print even pages. # Insert printed pages back into the printer in the right order and side, # as determined by the pencil, # and print odd pages. # USING LPR2 WITH A NETWORK-SHARED PRINTER: # Something very important about duplex printing on simplex printers, # is that while printing the second side, # you must synchronize the paper feed with the page being printed. # Now, if your printer is shared, you must prevent someone else's job # from being printed while your first-side-printed paper is in the paper feed! # Here is how I do resource-locking. # 1) verify that no other job is being printed with lpq # 2) when that's the case, enter critical section: # stop the printer by removing its paper feed. # 3) try to put your second-side-printing job in first position in the queue, # with command lpr. # 4) verify whether you succeeded with lpq # 5a) if you did succeed to have your job as first job, then # feed the printer with your first-side-printed paper, and there you are! # 5b) if you couldn't, then feed the printer with whatever paper was in # before, and try again later when the queue is emptied. # # This method does avoid your printing jobs being trashed by someone else; # however, it requires the queue to be empty for you to succeed; # if the shared printer's queue is never empty, this method won't work; # but if the printing load is that heavy, then maybe it's time # you should ask your administrators to purchase another printer, # perhaps doing double-sided documents directly. # # Of course, this method does not prevent usual printer failures (see below). # BUGS, MISFEATURES, AND OTHER PROBLEMS: # First of all, this is a mixed /bin/sh and Postscript program; # the existence of such languages is a bug in itself. # Please send feedback to God (in form of contributed free software), # so that this horrid state of things changes. # Because it uses /bin/sh, this program cannot reliably work with files # whose name contain spaces, carriage returns, null characters, etc. # But most unix software can't be trusted to manage such spaces well anyway, # so that people shouldn't (and generally don't) use space in filenames # under Unix, so LPR2 is not *particularly* limiting in such sense. # There is no soundness testing for the -p option, so beware and stick to # the Postscript syntax; however, an error will most probably result # in a run-time error at execution of the postscript program, # so the document will be rejected without any page being printed. # Also I'm using stack mark&restore to minimize risks of stack mishandling. # You are subject to all kinds of printer failure that can desynchronize # sheets of paper when printing their second side, like paper thrashing, # or like two sheets being eaten at a time, etc. This is all the truer since # there is a correlation between using lpr2 and having cheapo printers. # If your printer isn't too reliable, print the second side of only # a few sheets at a time (using option -p). Be careful! # INVOCATION: lpr2 [options] files # # The default behavior of LPR2 is to print the given document(s) duplex on a # simplex printer, with simple user interaction. # However, if any option is given to LPR2 (but the option to revert to # default behavior, --all), it will rather behave like a filter. # To have it send its output to the printer rather than to its # standard output, as it did in some older versions, use option -P, # perhaps in conjunction with option -z and -Z. # Several documents may be printed in sequence, one after the other. # The name "-" (minus sign, without quotes) means standard input, which is # also the default input for LPR2 (actually, this whole behavior is inherited # from the command cat(1), which LPR2 invokes). # # option what it means # -1,-o,--odd "print only odd pages" # -2,-e,--even "print only even pages" # -c,--cond "the string just after this is the postscript condition for # a page to be printed, e.g. '4 eq'" # -s,--select "print only the page whose number follows '-s' " # -p,--pages "print the pages listed after -p # in a comma-separated list of the form i-j[%k], # where i and j are first and/or last pages, # and k is a step. Mind the space between -p and the argument. # e.g. ``lpr2 -p 10-20%2'' prints every other page # from page 10 to page 20 (included)." # -a,--all "print even pages; prompt; print odd pages" (default) # -P,--print "do send to printer, not to standard output" # -N,--noprint "do not send to printer, but to standard output" (default) # -r,--reverse "print odd pages; prompt; print even pages in reverse # order" (beware: remove last sheet if odd number of pages) # NOT IMPLEMENTED YET, and not to be soon, as it involves much # more than just a postscript header. Use mpage or psrev (from # the psutil package) if you need such thing. Unhappily, those # packages are far less reliable than LPR2. # -z define the printing program to be following argument # e.g. -z lpr or -z cat # -Z following argument is to pass to the printing program # e,g, -Z "-lpr_option -second_lpr_option" # -A print by feeding the output to a file # choose file(s) with -Z file1 -Z file2 # I use it with -A -Z /dev/lp1 to print # on a computer w/o working lpd # -- stop parsing options: all the remaining arguments are # considered as filenames. ############################# ABOUT THE AUTHOR ################################ # THE AUTHOR: # I'm no PostScript guru *at all*. It's my first (and most certainly my last) # PostScript program. I've never read any Postscript book or official # documentation or programming recommendation; only ghostscript (gs) manpage # and examples. Postscript looks like a very interesting language to me; # very FORTH-like indeed. But whoever defined such lame (dynamic only) # semantics for variable binding deserves only shame. # I originally developped this program under Linux using Ghostscript 2.6.1 # in five minutes. I've actually spent much more time documenting it and # transforming it into a shell utility with bells and whistles than I did # writing the postscript stuff. Just try to evaluate and compare the size of # the postscript part, the size of the shell script part, and the size of the # comments (-8 # My main involvement is the TUNES project for a better computing system. # See my WWW page for more info about me or about TUNES (see below in .sig). # Man, I feel so talkative, when I'm editing this file ! ;-) # CREDITS: # - firstly, I must thank people from the Linux and free software community, # who contributed all the software and docs with which I can print. # - my greatest debt about understanding postscript goes to # Marc Espie (espie@ens.fr), author of lots of free software # (among which tracker and fprint), who not only explained me # the tricks of postscript, but also kindly directed me # to the right places where I could find docs and help. Cheers! # - finally, I'd like to thank all the people who sent me some feedback: # Chih Jen-Lin, Jean-Jacques Boivineau, Bill McGonigle, # Warwick Hockley, Rainer Blome, Michael Vergallen, Bob Russell, # Marty Leisner, Chris Hertel, Volker Tanger, Atai Levy, Kaustabh Duorah # AUTHOR'S .SIGNATURE AND ADDRESSES: #-- , , _ v ~ ^ -- #-- Fare -- fare@tunes.org -- Francois-Rene Rideau -- +)ang-Vu Ban -- #-- ' / . -- # #Dreams about The Universal (Distributed) Database. | | / #Snail mail: 6, rue Augustin Thierry 75019 PARIS FRANCE --- --- // #Phone: +33 1 42 02 67 35 /|\ /|\ // #WWW Homepage: "http://www.tunes.org/~fare/" /|\ /|\ / # #Join the TUNES project for a computing system based on computing freedom ! # TUNES is a Useful, Not Expedient System #URL: "http://www.tunes.org/~tunes/" ### END_COMMENTS ############################ Self-Releasing stuff ########################### # This stuff is plain fun: # having the program do all the dirty job at releasing itself! # You could strip all this section, as you should never use it, # unless you takeover LPR2 development (???). RELEASE_NOTE="\ I am pleased to announce the availability of LPR2 v${VERSION}, a utility to select which pages to print from a postscript document. LPR2 is originally intended and primarily used to print duplex (two-sided) documents on normal (one-sided) printers -- hence the name. LPR2 only does page selection, but works on just *any* postscript document you could normally obtain, even when more featureful software (e.g. mpage, psutil) will fail. LPR2 is a fun shell script, with outrageously extensive documentation included inside. LPR2 is free software with *small* non-binding license restrictions over GPL: SmileWare and CharityWare. See inside for details. LPR2 is available from my WWW site (see below) or from Linux FTP sites mirroring SunSITE [Note: for many reasons, SunSITE and mirrors may not be updated immediately]. New features in ${VERSION} as opposed to previously released versions are mostly minor bugfixes in documentation, platform compatibility, and option handling, plus administrative changes (like my internet address). The main postscript code itself has been quite stable for a few years. LSM entry included below for details... " SIGNATURE="\ ## Faré | VN: Уng-Vû Bân | Join the TUNES project! http://www.tunes.org/ ## ## FR: François-René Rideau | TUNES is a Useful, Not Expedient System ## ## Reflection&Cybernethics | Project for a Free Reflective Computing System ## " SEPA='------' RATOR='>8' SEPARATOR="$SEPA$RATOR" for i in F A Q ; do SEPARATOR="$SEPARATOR$SEPARATOR" ; done SEPARATOR="$SEPARATOR$SEPA" LGZ_SIZE="14109 " LSM_SIZE="1539 " LSM_DATE="09AUG98" Def_Entry () { LSM_ENTRY="\ Begin3 Title: lpr2 Version: ${VERSION} Entered-date: ${LSM_DATE} Description: duplex/page selection printing utility LPR2 is a simple shell script containing its own extensive documentation as comments. It allows selection of *any* set of pages in *any* postscript document without *any* loss in quality, which no other known utility does, (but it sends the whole stuff to the device printer, which is slow and inefficient as compared to other utilities *when by chance they do work*). Intended and used mostly to print duplex (recto/verso) documents on simplex printers. Do use it: duplex documents are only half as heavy, bulky, paper-costly and forest-destroying as simplex ones. Contribute saving the world. Keywords: printing, Postscript, select, page, duplex, recto, verso, double-sided, paper, both, sides, sheet, save the world Author: fare@tunes.org (Fare') Maintained-by: fare@tunes.org (Fare') Primary-site: http://www.tunes.org/~fare/files/ ${LGZ_SIZE}lpr2.gz ${LSM_SIZE}lpr2.lsm Alternate-site: sunsite.unc.edu /pub/Linux/system/printing ${LGZ_SIZE}lpr2-${VERSION}.gz ${LSM_SIZE}lpr2-${VERSION}.lsm Platforms: Any postscript device (typically ghostscript or a printer); a decent /bin/sh or better (e.g. bash) for scripting. Copying-policy: GPL+Restrictions(SmileWare+CharityWare) End " RELEASE_TEXT="\ ${RELEASE_NOTE} ${SIGNATURE} ${SEPARATOR} ${LSM_ENTRY}" } Def_Entry Get_Size () { printf '%-8d' `wc -c` } Update_Size () { TMPFILE=/tmp/lpr2 TMPFILEGZ=${TMPFILE}.gz FILE="$TMPFILE $TMPFILEGZ" cp $0 $TMPFILE gzip -f9 $TMPFILE LGZ_SIZE="`Get_Size < $TMPFILEGZ`" rm $TMPFILEGZ LSM_DATE=`date +%d%b%y | tr 'a-z' 'A-Z'` Def_Entry LSM_SIZE="`echo -n "$LSM_ENTRY" | Get_Size`" sed -e \ "s/^LSM_DATE=.*$/LSM_DATE=\"$LSM_DATE\"/ s/^LSM_SIZE=.*$/LSM_SIZE=\"$LSM_SIZE\"/ s/^LGZ_SIZE=.*$/LGZ_SIZE=\"$LGZ_SIZE\"/" \ < $0 > $TMPFILE && mv $TMPFILE $0 chmod a+x $0 FILE= } Check_for_maintainer () { case "$LOCALSYSTEM" in Kadath) RELEASE_DIR=/home/arc/save/linux ;; clipper) RELEASE_DIR=/users/92/maths/rideau/public_html/files ;; sweety) RELEASE_DIR=/home/fare/public_html/files ;; *) echo "Only the maintainer should release this software!" Exit 37 ;; esac } Release_Self () { Check_for_maintainer cd $RELEASE_DIR Update_Size Update_Size # reach fixed-point (hopefully) rm lpr2.gz lpr2.lsm cp $0 lpr2 gzip -f9 lpr2 mv lpr2.gz lpr2-$VERSION.gz echo -n "$LSM_ENTRY" > lpr2-$VERSION.lsm ln -s lpr2-$VERSION.gz lpr2.gz ln -s lpr2-$VERSION.lsm lpr2.lsm [ "x$TODO$GOTOPTS" = "xdoally" ] && Finish_Release } Register_LSM () { Check_for_maintainer echo -n "$LSM_ENTRY" | mail -s 'add' lsm@execpc.com } Finish_Release () { Check_for_maintainer Register_LSM echo -n "${RELEASE_TEXT}" | mail -s "LPR2 v${VERSION} duplex printing utility" \ linux-announce@news.ornl.gov echo "Don't forget to publish it to clipper and to sunsite" } ########################## The Postscript stuff ############################## redefshowpage () { # have as argument condition on page to show cat <<-END %!PS-Adobe-3.0 /.show.this.page.p { $1 } bind def /.page.number 1000001 7 string cvs def /.showpage.orig /showpage load def /.erasepage /erasepage load def /.showpage.lpr2 { 2 dict begin /p .page.number dup cvi dup 1 add 3 2 roll cvs pop 1000000 sub def mark p % (LPR2: showpage called for page ) print dup =only (.\n) print flush .show.this.page.p /c exch def cleartomark c end { % (LPR2: showing page.\n) print flush .showpage.orig } { % (LPR2: skipping page.\n) print flush .erasepage } ifelse % (LPR2: showpage ended.\n) print flush } def %Redefine showpage... /showpage { .showpage.lpr2 } bind def END } ########################## The shell functions ############################## doprinteven () { (redefshowpage "2 mod 0 eq" ; cat $FILES) | $SENDJOB } doprintodd () { (redefshowpage "2 mod 1 eq" ; cat $FILES) | $SENDJOB } doprintcond () { (redefshowpage "$COND" ; cat $FILES) | $SENDJOB } prompt () { echo "$@" > /dev/tty read dummy_answer < /dev/tty } doall () { prompt ' Feed the printer with blank sheets. If you don'"'"'t know how to feed the printer again to achieve printing on the "right" side, mark corners of the first sheets with a pencil. When you'"'"'re done, press "Enter". ' doprinteven prompt ' First, do wait for the thing to have been printed. When it'"'"'s done, press "Enter". ' prompt ' Now, if your printer issues pages in the wrong order, you have a problem. You'"'"'ll have to reorder everything twice. Next time, try --reverse option if it'"'"'s implemented. The first thing to do after having recovered the back sides of your printed documents is to ensure that no one else will use the printer while you'"'"'re printing on the other side. When this is done, feed the printer back with the same sheets, but place the sheets so that the other side will be printed (with the same top of page). If your document has an odd number of page, add a blank sheet at the end. When you'"'"'re done, press "Enter". ' doprintodd } doreverse () { reverse_NIY } reverse_NIY () { Not_implemented_yet "Function --reverse is " " (and not likely to ever be)." } Not_implemented_yet () { echo "$1" "NOT IMPLEMENTED YET" "$2" >&2 Exit 4 } calllpr () { $LPR $LPROPTS } append () { tee $LPROPTS > /dev/null } Exit () { cleanexit exit $@ } cleanexit () { [ -n "$FILE" ] && $RM $FILE } sigexit () { Exit 100 } ComputeEachCOND () { C_COND_0 $1 COND="$COND1" shift for i do C_COND_0 $i COND="$COND"' '"$COND1 or" done } C_COND_0 () { case "$1" in "-%"*) : a ; IFS=" -%" ; C_COND_1 1 x $1 ;; "-"*"%"*) : b ; IFS=" -%" ; C_COND_1 1 $1 ;; *"-%"*) : d ; IFS=" -%" ; C_COND_2 $1 ;; *"-"*"%"*) : e ; IFS=" -%" ; C_COND_1 $1 ;; "-"*) : c ; IFS=" -%" ; C_COND_1 1 $1 1 ;; *"%"*) : f ; IFS=" -%" ; C_COND_2 $1 ;; *"-") : g ; IFS=" -%" ; C_COND_1 $1 x 1 ;; *"-"*) : h ; IFS=" -%" ; C_COND_1 $1 1 ;; "%"*) : i ; IFS=" -%" ; C_COND_1 1 x $1 ;; *) : j ; IFS=" -%" ; C_COND_1 $1 $1 1 ;; esac } C_COND_1 () { C_COND_n $* } C_COND_2 () { C_COND_m $* } C_COND_m () { C_COND_n $1 x $2 } C_COND_n () { IFS=" " if [ "$1" = "$2" ] ; then COND1="p $1 eq" else if [ "$1" != 1 ] ; then COND1="p $1 ge" if [ "x$2" != "xx" ] ; then COND1="$COND1 p $2 le and" fi else if [ "x$2" != "xx" ] ; then COND1="p $2 le" else COND1=true fi fi fi if [ "$3" != 1 ] ; then COND1="$COND1 p $1 sub $3 mod 0 eq and" fi } ComputeCOND () { IFS=" ," ; ComputeEachCOND $1 IFS=" " } ######################### The command line interface ######################## LPR="lpr" # !!!! replace with your standard printing command # may be just "cat > /dev/lp1". lpr should be fine. RM="rm" # !!!! replace with your standard file deletion command # may be "/bin/rm -f --", but rm should be fine. # These should be ok and not need any modification TODO=doall LPROPTS= FILES= SENDJOB=cat # calllpr ParseOpts () { GOTOPTS=n while [ -n "$*" ] ; do i="$1" ; shift case "$i" in -a|--all) GOTOPTS=y ; TODO=doall ; SENDJOB=calllpr ;; -r|--reverse) reverse_NIY # Not implemented yet message... GOTOPTS=y ; TODO=doreverse ; SENDJOB=calllpr ;; -N|--noprint) GOTOPTS=y ; SENDJOB=cat ;; -P|--print) GOTOPTS=y ; SENDJOB=calllpr ;; -1|-o|--odd) GOTOPTS=y ; TODO=doprintodd ;; -2|-e|--even) GOTOPTS=y ; TODO=doprinteven ;; -c|--cond) GOTOPTS=y ; TODO=doprintcond ; COND="$1" ; shift ;; -s|--select) GOTOPTS=y ; TODO=doprintcond ; COND="$1 eq" ; shift ;; -p|--pages) GOTOPTS=y ; TODO=doprintcond ; ComputeCOND $1 ; shift ;; -z) GOTOPTS=y ; SENDJOB=calllpr ; LPR="$1" ; shift 2 ;; -Z) GOTOPTS=y ; LPROPTS="$LPROPTS $1" ; shift 2 ;; --) FILES="$FILES $*" ; shift $# ;; -A) SENDJOB=append ;; -v) echo "LPR2 v$VERSION" ; Exit 0 ;; -V|--version) echo "LPR2 -- version $VERSION" ; echo "$COPYRIGHT" ; Exit 0 ;; -h|--help) ( [ -x "$PAGER" ] && $PAGER $0 ) || less -MM "$0" || more "$0" || echo "Read the file "'``'"$0''" \ "for help about this program." Exit 0 ;; --lsm) echo -n "$LSM_ENTRY" Exit 0 ;; --selfrelease) Release_Self Exit 0 ;; --eval) $@ # undocumented backdoor for testing purpose... Exit $? ;; -*) echo "Unknow option \`\`$i''." >&2 echo "Read file $0 for help." >&2 Exit 3 ;; *) FILES="$FILES $i" ;; esac done if [ "$GOTOPTS" = "n" ] ; then TODO=doall ; SENDJOB=calllpr ; fi } DoIt () { : '":" is for debugging' : LPR=$LPR : TODO=$TODO : SENDJOB=$SENDJOB : LPROPTS=$LPROPTS : FILES=$FILES case "$SENDJOB$TODO$FILES" in catdoall*|catdoreverse*) echo "Incompatible options" ; Exit 1 ;; calllprdoall*" - "*|calllprdoreverse*" - "*|calllprdoall|calllprdoreverse) FILE=/tmp/lpr2-$$ trap sigexit HUP TERM cat > $FILE FILES=$FILE $FILES $TODO ;; *) $TODO ;; esac } ParseOpts "$@" DoIt cleanexit # # Read the executable script file "lpr2" with your usual pager for help. #