Subject: Linux Printing HOWTO (part 2/2) Newsgroups: comp.os.linux.announce,comp.os.linux.admin,comp.answers,news.answers From: gtaylor@cs.tufts.edu (Grant Taylor) Date: Fri, 18 Nov 1994 17:29:56 GMT Archive-name: linux/howto/printing/part2 Last-modified: 10 Jul 94 ---This is part 2/2--- At the time of writing I am quite unable to reproduce this error - I am using my debugged version of the net-2 lpd compiled with gcc-2.4.5 and libc-4.4.4 on kernel 0.99.14. 3.6 Where Do I Get A Printcap For Printer Model xxxxx? ====================================================== This question is essentially meaningless so please don't ask it on usenet See Also: The Semantics of /etc/printcap. 3.7 The Semantics of `/etc/printcap' ==================================== Given the similarity in appearance and name between `/etc/termcap' and `/etc/printcap' one could be forgiven for assuming that they contain analogous infomation. This is not the case. Whereas `/etc/termcap' contains informations about terminal *types* - (mostly escape seqences) printcap contains information about *specific* printers (like the directory that holds the spool queue, the device name of the printer and what room it's in). The information about a printer model's escape sequences and so on are held in the various "filters" which are programs called by `lpd' to drive the printer. `/etc/printcap' simply gives the locations of these filters. For details RTFM(printcap). [Alternatively the net-HOWTO has a summary of some of the more important fields.] One last point - you should always specify `suppress header' `:sh:' unless you have a *text* (not PostScript) printer and want banners. On a text printer they are usually a waste of time and paper. On a PostScript printer they usually stop your printer working. See Also: Burst/banner pages. 3.8 The Syntax of `/etc/printcap' ================================= Ideally RTFM(termcap) (yes, I said *termcap*) but since most people don't have TFM(termcap) here are the essentials. Lines starting with `#' are comments (as you might have guessed). For each printer usable from the `lpr' command on your system there is one logical line in the file. For the sake of readability each logical line may be spread over several physical lines by making the last character on all but the last physical line a backslash. Each logical line has the following format: NAME1|NAME2|NAME3:STRING_CAPABILITY=STRING:\ :NUMERIC_CAPABILITY#NUMBER:BOOLEAN_CAPABILITY: The leading spaces and colon on the second line are for readability only. A printer can have as many names as you like but conventionally the final name is used as a longhand description of the printer. (Still people are free to say `lpr -P "grotty teletype in room 213"' if that's the description you've given.) One of the names of your default printer must be `lp'. The list of capabilities can be as long as needed and the order is not significant. Each "capability" is denoted by a two character code. (The name "capability" comes form the file format's termcap heritage - parameter or attribute would be a more sensible terms.) [Note from Ross Biro: capabilities with 3 character names don't work properly which is why the serial port stuff in the old binaries failed.] Capabilities having string value and have a `=' delimiter between the capability name and the value while those having a numeric value use a `#' (actually they can use either a `#' or an `='). Boolean "capabilities" are true if they appear in the list and false if they do not. Special characters in a string value can be expressed using backslash-escaped sequences as in C; in addition, `\E' stands for ESC. `^' is also a kind of escape character; `^' followed by CHAR stands for the control-equivalent of CHAR. Thus, `^a' stands for the character control-a, just like `\001'. `\' and `^' themselves can be represented as `\\' and `\^' respectively. `\:' for `:' seems to work but the source code contains a warning that it can confuse the parser and `\072' is a better idea. Example: lp|bam|Epson FX-80:lp=/dev/lp1:sd=/usr/spool/lp1:sh:mx#0:\ :df=/usr/local/lib/magic-filter/lp.df:\ :if=/usr/local/lib/magic-filter/lp.if: The printer's name is `lp' (this is the printer that `lpr' uses by default). It's also known as `bam' or `"Epson FX-80"'. The printer is on `/dev/lp1' (aka AT-bus LPT1:). I don't want a burst page. I don't want a file length limit. Files queued by `lpr -d' are passed through `/usr/local/lib/magic-filter/lp.df' and those queued by `lpr' through `/usr/local/lib/magic-filter/lp.lf'. See also the next section. 3.9 An `/etc/printcap' gotcha ============================= Two `/etc/printcap' files can look identical and yet one works and the other doesn't. See if `lpc stat' reports a printer called ` :'. The last character on a continued line must be a backslash. If there are whitespace characters after the backslash then it doesn't register the next line as a continuation. 3.10 The Minimum /etc/printcap ============================== This is a silly question but it is frequently asked. The answer is `lp:sh' (that's 6 bytes including the required linefeed character on the end). To use this `/etc/printcap' you must make `/dev/lp' a symlink to your printer and create your spool queue directory as `/usr/spool/lpd'. (You might think that if you wanted banner pages you could loose the `:sh' but the termcap syntax requires at least one capability per entry). 3.11 How to prevent the `Staircase Effect' ========================================== Un*x terminates each line of a file with a linefeed but not a carriage return so taken literally a Un*x text file printed on an ASCII device will start each line below the end of the previous line. Some printers can be set to treat "linefeed" as "carriage return, linefeed", others can't. If yours can then do simply do that. If the printer cannot be fixed create a shell script filter that reads: #!/bin/sh if [ "$1" = -c ]; then cat else sed -e s/$/^M/ fi # the ``echo -ne'' assumes that /bin/sh is really bash echo -ne \\f Where `^M' is a carriage return character not a `^' followed by a `M'. To type `^M' in Emacs use the sequence `C-q C-m' and in vi use `C-v C-m'. Conventionally this script is called `/usr/lib/lpf'. If you have more than one such script a better idea is to keep them in a subdirectory, say `/usr/lib/lpd/'. The test of `$1' allows the insertion of carriage returns to be switched off by `lpr -l'. Install this filter as the `if' filter by putting `:if=/usr/lib/lpf:' (or whatever) in your `/etc/printcap' entry for the printer. Alternatively your printer may have an escape sequence that will set the way it handles linefeed characters. A simple filter that uses an `echo -ne' command to send this sequence may be appropriate. #!/bin/sh # Filter for HP printers to treat LF as CRLF # the ``echo -ne'' assumes that /bin/sh is really bash echo -ne \\033\&k2G cat echo -ne \\f 3.12 Resetting the printer between each file printed ==================================================== Either make your filters do it or define the `tr' "capability" in `/etc/printcap' to be your printer's font reset command. For details of the format of this string see the question on the format of printcap. This may not work if a printout crashes in the middle of an escape sequence - putting a lot of `^@' on the front may help but this probably won't be enough it you were printing raster graphics when the filter died. 3.13 Preventing formfeed after each file printed ================================================ If you don't have an `if' specified in `/etc/printcap' then `lpd' will automatically put a formfeed at the end of each file. If you're using a filter then it's up to the filter to decide if it wants to put a formfeed. To disable formfeed completely if you don't have an `if' put `:ff=:' in your `/etc/printcap'. But please note this suppresses the formfeed that would usually be printed if a filter dies. If you want formfeeds after text printouts but not on printouts printed with `lpr -l' then create the following `if' filter: #!/bin/sh # the ``echo -ne'' assumes that /bin/sh is really bash cat if [ "$1" != -c ]; then echo -ne \\f fi If you want a formfeed after `lpr -l' to be optional you can misuse the `-i' switch to suppress the formfeed with the following trick (after all `lpr -i -l' would usually not be implemented). #!/bin/sh cat # use lpr -i -l to print raw without trailing formfeed if [ "$1" != -c -o "$4" = -i0 ]; then # the ``echo -ne'' assumes that /bin/sh is really bash echo -ne \\f fi 3.14 Printing with lpd to a serial port ======================================= The first if lpd complains about "ioctl(TIOCEXCL)" being unimplemented you need a version of lpd that doesn't care (eg. lpd-590p2) There are two sets of flags which you will need to set, plus the baud rate (Note: the `fc' flag setting seems to override the `br#' capability, so be sure to set that correctly as well as the `br#'!). Each of the flags can have bits set and cleared. Clearing is done first, so specify the clear flags (`fc#' and `xc#') before the set flags (`fs' and `xs'). Setting the `br#' capability is self-explanatory. Example: `br#9600' It is very easy to translate from `stty' settings to printcap flag settings. If you need to, see the man page for stty now. Use stty to set up the printer port so that you can cat a file to it and have it print correctly. Here's what `stty -a' looks like for my printer port: dina:/usr/users/andy/work/lpd/lpd# stty -a < /dev/ttyS2 speed 9600 baud; rows 0; columns 0; line = 0; intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = ; eol2 = ; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; min = 1; time = 0; -parenb -parodd cs8 hupcl -cstopb cread -clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl ixon -ixoff -iuclc -ixany -imaxbel -opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 -isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt -echoctl -echoke The only changes between this and the way the port is initialized at bootup are `-clocal', `-crtscts', and `ixon'. Your port may well be different depending on how your printer does flow control. Once you have your stty settings right, so that `cat file > /dev/ttyS2' (in my case) sends the file to the printer, look at the file `/usr/src/linux/include/linux/termios.h'. This contains a lot of `#define's and a few structs (You may wish to cat this file to the printer (you do have that working, right?) and use it as scratch paper - I (Andrew Tefft did!). Go to the section that starts out /* c_cflag bit meaning */ #define CBAUD 0000017 This section lists the meaning of the `fc#' and `fs#' bits. You will notice that the names there (after the baud rates) match up with one of the lines of stty output. Didn't I say this was going to be easy? Note which of those settings are preceded with a - in your stty output. Sum up all those numbers (they are octal). This represents the bits you want to *clear*, so the result is your `fc#' capability. Of course, remember that you will be setting bits directly after you clear, so you can just use `fc#0177777' (I do). Now do the same for those settings (listed in this section) which do not have a - before them in your stty output. In my example the important ones are CS8 (0000060), HUPCL (0002000), and CREAD (0000200). Also note the flags for your baud rate - mine is 0000015. Add those all up, and in my example you get 0002275. This goes in your `fs#' capability (`fs#02275' works fine in my example). Do the same with set and clear for the next section of the include file, "c_lflag bits". In my case I didn't have to set anything, so I just use `xc#0157777' and `xs#0'. Once your printcap is set up, try it out. If things don't work, see the next section. 3.15 cat works to the serial port, but not lpd (1) ================================================== Generally getting lpd up and running is explained elsewhere, but if you are having trouble with serial port settings you can prevent `lpd' from trying to configure your port by treating you printer as one that does not present a normal device interface. See Also: Printers not in /dev. 1. Set your printer (in your printcap) to `/dev/null1'. (`mknod /dev/null1 c 1 3' because you don't want `/dev/null' to be opened exclusively). remove the baud rate and flags settings from your printcap. 2. Create a script such as this: #!/bin/sh echo if: $* >> /var/spool/lpd/results # /dev/lp is linked to /dev/ttyS2 which has the printer exec your-old-input-filter $* > /dev/lp ...or if you didn't have an old `if' installed... #!/bin/sh echo if: $* >> /var/spool/lpd/results cat > /dev/lp # the ``echo -ne'' assumes that /bin/sh is realy bash echo -en \\f > /dev/lp Make sure it's world-executable and world-readable. Try out your script (`/usr/lib/lpd/if < SOMEFILE') and see if it prints. 3. Set the `if' capability in your printcap to call this script, e.g. `if=/usr/lib/lpd/if' 4. Use stty to correctly set your port settings. Try to print now. You should be able to tell if things are being spooled, and things *should* be printed, if your manual testing of the `if' script works. But this is a kludge, so the idea is not to use the `if' script. Assuming the above method using the `if' filter works and that you believe that you have specified what you think are the correct flags and baud rate in printcap; check `stty -a < /dev/ttyS2' (or whatever your printer port is). If the settings are not correct, check your flags against your printout from termios.h. If the settings are *way* not correct, you may need a fixed lpd. The patch follows, and you can probably see why it's needed :-) Note: this patch is reversed and has already been applied (uh... unapplied :-) ) to lpd-590p2 so don't apply it if you already have that version or later. (the patch is coming in just a sec) When I was setting mine up, I followed a sequence like this: lprm WHATEVER # (make sure queue is empty and lpd is running) stty CORRECT SETTINGS < /dev/ttyS2 lpr SOMETHING SMALL stty -a < /dev/ttyS2 # (often had to ctrl-c out of this one) twiddle with flags lprm WHATEVER # make sure queue is empty again... Here's the patch (I it's reversed so apply it with `-R' - or, in practice, by hand!): -------------------------------Cut Here------------------------------------- *** lpd-590/lpd/printjob.c Thu Jul 8 20:56:59 1993 --- lpd-590/lpd/printjob.c~ Sat Feb 27 09:07:01 1993 *************** *** 1271,1277 **** } #ifdef LINUX ttybuf.c_cflag &= ~FC; /* not quite right! */ ! ttybuf.c_cflag |= FS; /* not quite right! */ #else ttybuf.sg_flags &= ~FC; ttybuf.sg_flags |= FS; --- 1271,1277 ---- } #ifdef LINUX ttybuf.c_cflag &= ~FC; /* not quite right! */ ! ttybuf.c_cflag |= ~FS; /* not quite right! */ #else ttybuf.sg_flags &= ~FC; ttybuf.sg_flags |= FS; -------------------------------Cut Here------------------------------------- 3.16 Printers that are not simple devices ========================================= [Firstly I'll explain the subject.] The most common example is a printer that is connected via a network in some strange way. For example consider a printer connected to a host with which you can only communicate via E-mail. To use such a printer through `lpr' the `lp' capability of the print queue should be directed to a `/dev/null' type device (e.g. `mknod /dev/null1 c 1 3') but not `/dev/null' itself as `lpd' opens the device exclusively. Each filter must must explicitly uuencode and mail its output. In more complex cases if you already have an `if' or `of' filter for a strangely connected printer then other filters can pass their output to/through this filter to avoid duplication of effort. In this case the `if' filter should usually be called with the `-c' switch to minimise the further manipulations if performs. I've heard someone has had some success trying something like this with Novell NetWare and the free mail transfer agent "Charon". 3.17 Generating burst or banner pages ===================================== For a simple text printer (in particular not PostScript) and a simple text banner simply take `:sh:' out of the printcap record. If you want to prevent the banner comming out in whatever font was last used on the printer then define the `tr' "capability" to be your printer's font reset command. If you want a fancy customised banner (or have a PostScript printer) leave `:sh:' in the printcap and make each of your filters print the banner. All the information to put on the banner is included in the filter's positional parameters. RTFM(printcap) for details. [ If you're using 's magic-filter package then call the code to print the banners from the config script. ] 3.18 Spooling text to a PostScript printer ========================================== You need a filter based on a program that converts ascii to PostScript. The most well known of these is `enscript' but it's also the hardest to find (being non-free). Others include `a2ps', `nenscript', and `mpage'. See Also: Printing text via PostScript. 3.19 Why graphics files are sometines truncated =============================================== This is usually because you've got a limit set on the maximum size file that can sit in the spool queue. Put `mx#0' in your printcap. 3.20 Why `lpr -i' doesn't work ============================== To get `lpr -i' to work you need a filter installed as `if' that implements it. The `-i' switch is simply passed on by `lpd' to the filter. The filter called `lpf' that comes with `lpd' supports this feature but can only be used to print text. If you whant to use this program but still want your filter to do some printer specific initialisation then write script thus: #!/bin/sh # My initialisation stuff goes here exec /usr/lib/lpf $* More reasonably you could have your filter script send the printer left margin sequence. #!/usr/bin/perl # This example is in perl for a change because converting numbers # to characters is tricky in shell script for ($i=0; !($_ = $ARGV[$i]) || !/^-i([0-9])+/; $i++) {} print pack("cAc",27,"l",$1); while () { print; } 3.21 Why `lpr -p' doesn't work? =============================== Because it's broken. `lpd' always thinks that the printer is 0 characters wide regardless of what `/etc/printcap' or the `lpr' arguemnts say. The lpd-FAQ contained a patch but it has now been applied to lpd-590p1 and later. (Appologies to anyone who wanted this patch after the lpd-FAQ merged with printing-how.to. It was dropped in the mistaken belief that a new release of lpd-590 was iminent). One other thing: `lpd' calls `pr' by full pathname so if you keep `pr' somewhere different from `/usr/bin/pr' you will need a symlink. (Where `lpd' expects to find `pr' may vary from version to version). 3.22 `lpc' and `lpq' warning of missing daemons =============================================== One `lpd' process runs all the time and it spawns children to handle each printer as needed. The health of the master daemon is not explicity reported by `lpc' but the absence of errors indicates that it is healthy. See Also: lpd not working. The `lpc stat' command will display the message "no daemon present" for each queue that is not actually printing at the time - this is completely normal. If printing has been disabled or the queue is empty then this is not an error condition. `lpq' is even more alarmist and will say "Warning: no daemon present". If the daemon is absent when the queue has entries and has not been explicitly stopped then this warning probably indicates an error in a filter. Fix the filter then use `lpd up QUEUE-NAME' to restart it. Sometimes when shutting down a printer `lpc' will get confused and try to kill a non existant daemon. This leads to irritating but harmless error messages. In lpd-590p2 these are much rarer. 3.23 Using `lpr' over a network =============================== To print on the printer listed as `foo' in the printcap on machine `bar.baz.net' from the machine `mine.baz.net' you put an entry like this in your `/etc/printcap' (on `mine.baz.net'): foo:lp=:rm=bar.baz.net:rp=foo:sd=/usr/lpd/spool/foo: and, of course, create the spool directory `/usr/lpd/spool/foo'. There's no point specifying filters and the like in `mine.baz.net:/etc/printcap' as it's the ones in `bar.baz.net:/etc/printcap' that will get used. On the machine `bar.baz.foo', you need to put `mine.baz.net' on a line by itself in either `/etc/hosts.equiv' or `/etc/hosts.lpd'; note that putting it in `/etc/hosts.equiv' will allow for unauthenticated logins as well as printing. `/etc/hosts.lpd' is for printing only. The machines listed in `/etc/hosts.*' should be described canonical names or numbers as lpd starts with the IP address and performs a revervse DNS lookup to get the name. If you are not sure of cannonical name you can just list all the names you know for a machine. (If you have `dig' then the command `dig -x A.B.C.D' can be used to get the canonical name of IP address A.B.C.D.) If the printer server is not nunning a BSD style spooler then it should still be possible to get it to work but the authority files may have a different names or formats. For example Chris Nystrom found that he had to create a file on the remote machine called `/usr/spool/lp/admins/lp/Systems' that listed his Linux box's name. We do not know if this is a SYSV thing or something exclusive to dynix/ptx 2.0.3 that he is using on his Sequent. If you can't get remote printing to work thrugh lpd you may be able to simply use remote command exectution like this: rsh bar.baz.net "lp -dlp" < FILE This example would be for a remote system using a SYSV type printing system on host `bar.baz.net'. 3.24 Writing lpd filters ======================== In normal Un*x terminology, filters are just programs (so they must have execute permission) that read a stream from their standard input and write to their standard output. lpd filters are filters in the sense that thay read STDIN and write to STDOUT, but are unusual in that they may assume that their standard input is a random acess file file and may perform lseek() operations on it. All lpd filters have a common command line syntax (or more often simply ignore command line parameters). For details of the command line parameters RTFM(printcap). If you want to write a shell script filter it must have a #!/bin/sh (or perl or csh) header. Here is the generic form of a filter to accept PostScript. #!/bin/sh /PATH.../gs -q -dSAFER -dNOPAUSE -r??? -sDevice=?????? -sOutputFile=- - Place the full pathname of the script as one of the filters (but not `of'!) parameter in the printcap for your printer. I suggest putting such scripts in `/usr/lib/lpd/'. It is also usual to keep filters in the spool directories but this goes against normal practice of keeping programs and data neatly apart. (`-dSAFER' attempts to protect against PostScript interpreter security holes, `-q' and `-dNOPAUSE' make it run nonstop, and Device is the appropriate special file for your printer). Here is an Epson FX-80 dvi filter using ghostscript: #!/bin/sh /usr/TeX/bin/dvips -f | \ /usr/bin/gs -q -dSAFER -sDEVICE=eps9high -r120x216 \ -dNOPAUSE -sOutputFile=- - More tools useful for making filters are described elsewhere in this document. 3.25 Debuging lpd filters ========================= It's easier to debug filters if you test them in an immediate shell before you install them. (If your filter makes use of its command line arguments you'll have to specify them too). `my-new-filter /dev/lp1' A trick most people find useful when testing filters that make use of their command line arguments is to include `echo $* >>/tmp/filter-log' near the top of the script. If the filter works when you test it but still doesn't work when called by `lpd' then you may have forgotten the `#!/bin/sh' header. You may also need to set PATH within the script since the daemon's PATH may not have everything you need. Note also that the filter is run with uid=daemon so any programs it calls sould be world executable. 3.26 Output (`of') filters ========================== Never use these. (Well strictly speaking there are circumstances but you're unlikey to meet them). Recently (early '94) there has been a spate of preople on c.o.l.help advokating the use of output filters. Using `of' filters means that if a printout is queued while another is already printing the 2 will be run together with a form-feed between. Any printer initialisation or file type detection will therfore not be performed for the second file and it will probably be printed incorrectly. There are other more subtle ways in which output filters can do unexpected things. IMHO: If using an output filter is the answer, it was probably a silly question. This is Info file Printing-HOWTO.info, produced by Makeinfo-1.55 from the input file printing.texinfo. A guide to printing and previewing files under the Linux operating system. Copyright (C) 1994 by Grant Taylor and Brian McCauley 3.27 Getting filters for given printers ======================================= From: B.A.McCauley@bham.ac.uk (Brian McCauley) Because writing a filter usually takes about 10 minutes once you've found the right program (`gs', `dvilj' etc.) there's little call for ftp archives of printer filters but we are thinking of creating an extensive example file to go with this document. If you already have a program to print, say, DVI on your printer by some mechanism then making it into a filter is usually a matter of writting trivial shell script See Also: Writing lpd filters. If the program you are using insists on reading a names file as input see the next question. Text mode filters are trivial too (see this HOWTO) unless you want lpr to have a choice of fonts in which case they are slightly harder than trivial. You will probably want to insert and `echo -ne' command at the beginning and end of your filter to set up the font etc to your liking. 3.28 Filters from programs that won't read STDIN ================================================ Some of the programs that are used in writing `lpd' filters are not capable of taking their input from their standard input. For example `dvilj2p' insists on a named file as its input (and what's more expects one with a `.dvi' suffix) so do this: #!/bin/sh ln -s /proc/self/fd/0 /tmp/$$.dvi dvilj2p /tmp/$$ rm /tmp/$$.dvi Note: If it wasn't for the fact that `dvilj2p' adds a `.dvi' suffix you wouldn't need the temporary symlink and could just specify `/proc/self/fd/0' directly. People who use this trick often usually permanently `ln -s /proc/self/fd/0 /dev/stdin'. If you're highly security concious and don't allow access to `/proc' you'll need to create a temporary file. 3.29 Having many filters ======================== Historically the `lpr' command was created to support a finite set of possible file types. You can, in fact, use any of the filters for any reason. If you're never going to use Benson Varian raster files you could use the `-v' switch for GIF files. You could even use `-d' for low res and `-v' for high res. Remember that if you create a filter for a file format that takes a long time to process then your printer may sit idle between print jobs even when there are things in the queue. If you are on a network remember that the filter setups go on the print server. One way to avoid running out of filter options is to define several logical printers in `/etc/printcap' that all point to the same physical one and put each filter in the `if' field of a different printcap entry. This has the advantage that you can set the `PRINTER' enviroment variable to choose your filter rather than having to specify it on the command line each time. One small problem with this is that you have no control over the order in which files from separate queues are printed. Another (and these days more common) way to avoid running out of possible types is to use magic filters. 3.30 Magic Filters ================== Magic filters deduce their input files' types from `magic numbers' (distictive byte patterns at particular offsets). Magic filters are usually perl scripts, shell scripts or C programs that simply identify the file type then call the appropriate non-magic filter. Blatent plug :-) Brian has a generic magic filter bash script that selects the right filter to use based on the output of the `file' command. With a suitable magic filter (and 3 associated non-magic filters) you can do things like: lpr -d file1.dvi file2.div.Z file3.ps file4.texinfo.gz (BTW confguring `lpr' to handle texinfo files is getting a bit silly). This is now on the mailserver or at: `tsx-11.mit.edu:pub/linux/sources/usr.bin/magic-filter-0.4.tar.gz' (Although the release number will possibly change in future). `apsfilter' is a rather easier to use shell script that requires no additional filters and which is pre-configured for HP compatible laser printers. This is also available on the mailserver. An example written in C, which may be easily adapted to most installations is available from the printing mail server as `lpr_if.c'. Magic filters should never specified as `of' as the output filter only gets called once if a number of files are printed without a gap. There are other more subtle problems too using `of'. IMHO (Brian) magic filters as `if' are inelegant as they may prevent you, say, listing a PostScript or nroff file. (Most people disagree with me on this point.) 3.31 Magic Filter Examples ========================== The following is an example of a magic shell script which should take either PostScript or text and deal with it: #!/bin/sh # This is based on a script I received from Scott Doty and which was # written by Keith Walker. Keith's script made use of the fact that # lpd passes options to if: # # -w -l -i -n -h # # to print text out well at any size. This one does not. These options # are also handy if you want to do your own snazzy header page, much # like NeWSPrint from Sun does (although running PostScript through # the display server to get it interpreted is a bit much :) # # # gs will reset the printer anyway, so the this text setup doesn't matter. # setup should include the escape code for \n conversion, if applicable. # printf "" read first_line first_two_chars=`expr $first_line : '\(..\)'` if [ "$first_two_chars" = "%!" ]; then # it's PostScript /usr/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=??????? -sOutputFile=- - else # it's plain text echo -n $first_line cat printf "\014" fi Note that for the paranoid, shell scripts run as someone other than the user are sometimes a security hole, but this is not the case with lpd filters as the script's environment is not under the control of the potential cracker. 4 Previewing ************ These sections describe various ways to preview things under Linux - that is, how to view them in a way approximating their final form without printing them out. 4.1 ghostview ============= Ghostview, a companion program for `gs', previews PostScript on an X display. It also lets you select individual or ranges of pages from a PostScript document to print using `lpr'. The new version, 1.5, has fixed a few glitches which never bothered me but may make a difference to you. It also calls `gs' with the `-dSAFER' option and has a few more resource and command-line options relative to 1.4.1. The real installation is from: `prep.ai.mit.edu:/pub/gnu/ghostview-XXX.tar.gz' It builds out of the box. Ghostview requires `gs' to work. The new version of `gs', 2.6.x, will use X display fonts in an effort to improve legibility at the low resolutions of a video monitor (a previous failing of this pair relative to commercial display-PostScript based systems). This works very well for me at least, at the expense of exact character positioning (X fonts have different widths). In fact, I thought that Ghostview looks better than Sun's pageview the other day when I looked at the same page in oth programs side-by-side. Ghostview/Ghostscript also has much more intelligent color handling than pageview. You might wish to let `gs' render some Type 1 fonts you install instead of using platform fonts (or the awful fonts `gs' comes with. To do this while in Ghostview (or in any situation involving the X11 driver), place `ghostscript.useExternalFonts: false' in your `.Xdefaults' file, and the platform fonts will not be used. This is part of a message posted to gnu.ghostscript.bug by Tim Theisen : (note that the usual Linux X-server, XFree, is simply an enhanced version of MIT's effort at an i386 X-server (X386), and does contain the X11R5 Type 1 rasterizer which I beleive was contributed by IBM.) Ghostscript now uses the X Toolkit to pick up X Resources. Now ghostscript uses the standard X rules that allow more specific resources to override less specific ones giving users the full power of X resources to control the X11 driver. It also allows system administrators to establish an application defaults file with resources specific to their ghostscript installation. The customization choices mentioned in make.doc have been moved into X resources and are now configured at run time rather than compile time. Sorry, this section of make.doc did not get revised for the 2.6.1 release. If `useBackingPixmap' is set, ghostscript will attempt to allocate a backing pixmap. If one cannot be allocated, ghostscript will issue a warning and ask for backing store instead. (Since there were insufficient resources for a backing pixmap, the X server may not provide backing store either.) Color Handling was totally revamped for gs 2.6. Ghostscript first checks for a suitable standard colormap. If you have static colormap in your X server, it would be best to store a standard colormap property on the root window describing the color layout. Ghostscript will then be able to take full advantage of the device. If you have a standard colormap installed, ghostscript will start slightly faster since it does not have to allocate colors for a cube or ramp. If no standard colormap is available, ghostscript will allocate an RGB cube or gray ramp. Ghostscript tries for a 5x5x5 cube on a color device, and a 128 gray ramp on grayscale devices. It will never ask for more than 1/2 of the colors for a RGB cube or gray ramp. It also takes into account the number of significant bits per pixel. (i.e. It won't ask for 128 gray levels if you only have 16 available.) Ghostscript will attempt to allocate colors that are off the color cube/ramp as the picture is being rendered. Ghostscript will keep track of 256 dynamic colors. After all these are allocated, ghostscript asks the X server directly. The foreground and background color can be set explicitly. This is important for the visually impaired and when using the ghostview widget. Color Resources: 1. `palette'(`Palette'): Default value: `Color'. Other allowable settings: `Grayscale', `Monochrome'. The palette resource is used to restrict the palette used for display. One can set palette to `Grayscale' or `Monochrome' to see how a file would be rendered in grayscale or monochrome on a color display. I use it to avoid dithering of gray- scale figures on a color display with 4-bit DACs. 2. `maxGrayRamp'(`MaxGrayRamp'): Default value: 128. Maximum number of gray levels that ghostscript will attempt to allocate. (It won't try for more than this on an 8-bit pseudo color display even if you set it higher.) Set this lower if you want a smaller ramp and would prefer ghostscript to use dynamic colors. 3. `maxRGBCube'(`MaxRGBCube'): Default value: 5. Maximum number of colors levels that ghostscript will attempt to allocate. (It won't try for more than this on an 8-bit pseudo color display even if you set it higher.) Set this lower if you want a smaller ramp and would prefer ghostscript to use dynamic colors. I believe these values to be a good compromise between dynamic allocation and fall back onto a fairly good color cube for dithering. You can use the foreground and background colors to accomplish "reverse video". However, if you have a grayscale device, it may be better to reverse the gray ramp using the following PostScript code fragment: [{1 exch sub} /exec load currenttransfer /exec load] cvx settransfer The X11 driver now supports native X11 fonts. If you have installed the HP XLFD font extensions into your font or X server. Ghostscript will also be able to use platform fonts at rotations of 90 degrees, with mirroring, and anamorphic scaling. The X11 driver does most if its work silently. You can get it to report when it is using an X11 font by setting the logExternalFonts boolean in your X resources. The X11 driver is setup to use the standard fonts distributed with X11R5. We purchased the Adobe Type Manager and the Adobe Plus Pack. These font packages give all the fonts normally found in the Apple LaserWriter Plus. The X11 driver is setup to handle these fonts as well. (They are a superset of the bitmap fonts distributed with X11.) You may set the regularFonts, symbolFonts, or dinbatFonts resources if you have different fonts available. Each font name must have 7 dashes or it will be ignored. Minimize the use of wildcards to promote faster matching. (I once encountered an X server that took many seconds to do a font lookup when wildcards were carelessly used.) There is a different list of fonts for each common encoding. Regular fonts may be accessed in standard or ISO Latin 1 encoding. The bdf files that are distributed with X11 are in the ISO Latin 1 encoding. This leaves out the ligatures. Luckily, the ligatures are present in the bdf files, but are not given an encoding, essentially commenting them out. You can use the `fixfont' program from the xproof distribution (`Ftp.Cs.Wisc.Edu:/Pub/X/Xproof.Tar.Z', or `Ftp.X.Org:/Contrib/Xproof.Tar.Z') to reencode the bdf files and build X11 fonts that contain the ligatures (i.e standard encoding). If you have the Type1 fonts mentioned above, and you installed the Type1 rasterizer into you font or X server, you can use the appended fonts.scale to name your fonts so that ghostscript can find them. Font resources: 1. `useExternalFonts'(`UseExternalFonts'): Default value: true. This resource controls whether X11 fonts will be used. 2. `useScalableFonts'(`UseScalableFonts'): Default value: true. This resource controls whether scalable fonts will be used. If you have an outline scaler in your X server, you should have this on. If you have an X terminal, you may get slightly better performance with this on. If you have to use the X11 bitmap scaler, turn this off. Fonts scaled by the bitmap scaler look worse than the default ghostscript fonts. 3. `logExternalFonts'(`LogExternalFonts'): Default value: false. Controls whether to report when X11 fonts are being used. The following fonts.scale makes all of the fonts of the Adobe Type Manager and Adobe Plus pack available in standard and ISO Latin 1 encoding. (We were able to purchase the above two packages at an educational discount price of $150.) 70 agw_____.pfb -Adobe-ITC Avant Garde Gothic-Book-r-normal--0-0-0-0-p-0-iso8859-1 agwo____.pfb -Adobe-ITC Avant Garde Gothic-Book-o-normal--0-0-0-0-p-0-iso8859-1 agd_____.pfb -Adobe-ITC Avant Garde Gothic-Demi-r-normal--0-0-0-0-p-0-iso8859-1 agdo____.pfb -Adobe-ITC Avant Garde Gothic-Demi-o-normal--0-0-0-0-p-0-iso8859-1 bkl_____.pfb -Adobe-ITC Bookman-Light-r-normal--0-0-0-0-p-0-iso8859-1 bkli____.pfb -Adobe-ITC Bookman-Light-i-normal--0-0-0-0-p-0-iso8859-1 bkd_____.pfb -Adobe-ITC Bookman-Demi-r-normal--0-0-0-0-p-0-iso8859-1 bkdi____.pfb -Adobe-ITC Bookman-Demi-i-normal--0-0-0-0-p-0-iso8859-1 com_____.pfb -Adobe-Courier-Medium-r-normal--0-0-0-0-m-0-iso8859-1 coo_____.pfb -Adobe-Courier-Medium-o-normal--0-0-0-0-m-0-iso8859-1 cob_____.pfb -Adobe-Courier-Bold-r-normal--0-0-0-0-m-0-iso8859-1 cobo____.pfb -Adobe-Courier-Bold-o-normal--0-0-0-0-m-0-iso8859-1 hv______.pfb -Adobe-Helvetica-Medium-r-normal--0-0-0-0-p-0-iso8859-1 hvo_____.pfb -Adobe-Helvetica-Medium-o-normal--0-0-0-0-p-0-iso8859-1 hvb_____.pfb -Adobe-Helvetica-Bold-r-normal--0-0-0-0-p-0-iso8859-1 hvbo____.pfb -Adobe-Helvetica-Bold-o-normal--0-0-0-0-p-0-iso8859-1 hvn_____.pfb -Adobe-Helvetica-Medium-r-Narrow--0-0-0-0-p-0-iso8859-1 hvno____.pfb -Adobe-Helvetica-Medium-o-Narrow--0-0-0-0-p-0-iso8859-1 hvnb____.pfb -Adobe-Helvetica-Bold-r-Narrow--0-0-0-0-p-0-iso8859-1 hvnbo___.pfb -Adobe-Helvetica-Bold-o-Narrow--0-0-0-0-p-0-iso8859-1 ncr_____.pfb -Adobe-New Century Schoolbook-Medium-r-normal--0-0-0-0-p-0-iso8859-1 nci_____.pfb -Adobe-New Century Schoolbook-Medium-i-normal--0-0-0-0-p-0-iso8859-1 ncb_____.pfb -Adobe-New Century Schoolbook-Bold-r-normal--0-0-0-0-p-0-iso8859-1 ncbi____.pfb -Adobe-New Century Schoolbook-Bold-i-normal--0-0-0-0-p-0-iso8859-1 por_____.pfb -Adobe-Palatino-Medium-r-normal--0-0-0-0-p-0-iso8859-1 poi_____.pfb -Adobe-Palatino-Medium-i-normal--0-0-0-0-p-0-iso8859-1 pob_____.pfb -Adobe-Palatino-Bold-r-normal--0-0-0-0-p-0-iso8859-1 pobi____.pfb -Adobe-Palatino-Bold-i-normal--0-0-0-0-p-0-iso8859-1 sy______.pfb -Adobe-Symbol-Medium-r-normal--0-0-0-0-p-0-iso8859-1 tir_____.pfb -Adobe-Times-Medium-r-normal--0-0-0-0-p-0-iso8859-1 tii_____.pfb -Adobe-Times-Medium-i-normal--0-0-0-0-p-0-iso8859-1 tib_____.pfb -Adobe-Times-Bold-r-normal--0-0-0-0-p-0-iso8859-1 tibi____.pfb -Adobe-Times-Bold-i-normal--0-0-0-0-p-0-iso8859-1 zcmi____.pfb -Adobe-ITC Zapf Chancery-Medium-i-normal--0-0-0-0-p-0-iso8859-1 zd______.pfb -Adobe-ITC Zapf Dingbats-Medium-r-normal--0-0-0-0-p-0-iso8859-1 agw_____.pfb -Adobe-ITC Avant Garde Gothic-Book-r-normal--0-0-0-0-p-0-adobe-fontspecific agwo____.pfb -Adobe-ITC Avant Garde Gothic-Book-o-normal--0-0-0-0-p-0-adobe-fontspecific agd_____.pfb -Adobe-ITC Avant Garde Gothic-Demi-r-normal--0-0-0-0-p-0-adobe-fontspecific agdo____.pfb -Adobe-ITC Avant Garde Gothic-Demi-o-normal--0-0-0-0-p-0-adobe-fontspecific bkl_____.pfb -Adobe-ITC Bookman-Light-r-normal--0-0-0-0-p-0-adobe-fontspecific bkli____.pfb -Adobe-ITC Bookman-Light-i-normal--0-0-0-0-p-0-adobe-fontspecific bkd_____.pfb -Adobe-ITC Bookman-Demi-r-normal--0-0-0-0-p-0-adobe-fontspecific bkdi____.pfb -Adobe-ITC Bookman-Demi-i-normal--0-0-0-0-p-0-adobe-fontspecific com_____.pfb -Adobe-Courier-Medium-r-normal--0-0-0-0-m-0-adobe-fontspecific coo_____.pfb -Adobe-Courier-Medium-o-normal--0-0-0-0-m-0-adobe-fontspecific cob_____.pfb -Adobe-Courier-Bold-r-normal--0-0-0-0-m-0-adobe-fontspecific cobo____.pfb -Adobe-Courier-Bold-o-normal--0-0-0-0-m-0-adobe-fontspecific hv______.pfb -Adobe-Helvetica-Medium-r-normal--0-0-0-0-p-0-adobe-fontspecific hvo_____.pfb -Adobe-Helvetica-Medium-o-normal--0-0-0-0-p-0-adobe-fontspecific hvb_____.pfb -Adobe-Helvetica-Bold-r-normal--0-0-0-0-p-0-adobe-fontspecific hvbo____.pfb -Adobe-Helvetica-Bold-o-normal--0-0-0-0-p-0-adobe-fontspecific hvn_____.pfb -Adobe-Helvetica-Medium-r-Narrow--0-0-0-0-p-0-adobe-fontspecific hvno____.pfb -Adobe-Helvetica-Medium-o-Narrow--0-0-0-0-p-0-adobe-fontspecific hvnb____.pfb -Adobe-Helvetica-Bold-r-Narrow--0-0-0-0-p-0-adobe-fontspecific hvnbo___.pfb -Adobe-Helvetica-Bold-o-Narrow--0-0-0-0-p-0-adobe-fontspecific ncr_____.pfb -Adobe-New Century Schoolbook-Medium-r-normal--0-0-0-0-p-0-adobe-fontspecific nci_____.pfb -Adobe-New Century Schoolbook-Medium-i-normal--0-0-0-0-p-0-adobe-fontspecific ncb_____.pfb -Adobe-New Century Schoolbook-Bold-r-normal--0-0-0-0-p-0-adobe-fontspecific ncbi____.pfb -Adobe-New Century Schoolbook-Bold-i-normal--0-0-0-0-p-0-adobe-fontspecific por_____.pfb -Adobe-Palatino-Medium-r-normal--0-0-0-0-p-0-adobe-fontspecific poi_____.pfb -Adobe-Palatino-Medium-i-normal--0-0-0-0-p-0-adobe-fontspecific pob_____.pfb -Adobe-Palatino-Bold-r-normal--0-0-0-0-p-0-adobe-fontspecific pobi____.pfb -Adobe-Palatino-Bold-i-normal--0-0-0-0-p-0-adobe-fontspecific sy______.pfb -Adobe-Symbol-Medium-r-normal--0-0-0-0-p-0-adobe-fontspecific tir_____.pfb -Adobe-Times-Medium-r-normal--0-0-0-0-p-0-adobe-fontspecific tii_____.pfb -Adobe-Times-Medium-i-normal--0-0-0-0-p-0-adobe-fontspecific tib_____.pfb -Adobe-Times-Bold-r-normal--0-0-0-0-p-0-adobe-fontspecific tibi____.pfb -Adobe-Times-Bold-i-normal--0-0-0-0-p-0-adobe-fontspecific zcmi____.pfb -Adobe-ITC Zapf Chancery-Medium-i-normal--0-0-0-0-p-0-adobe-fontspecific zd______.pfb -Adobe-ITC Zapf Dingbats-Medium-r-normal--0-0-0-0-p-0-adobe-fontspecific 4.2 gspreview ============= This is another front-end for Ghostscript. I have gotten and built it, and actually preferred the user interface, but it had a few bugs. It didn't seem as full-featured as ghostview, though. (Not that there are all *that* many features in ghostview, but it does its job well). `ftp.x.org:/contrib/gspreview...' 4.3 xdvi ======== A beautifully legible previewing program for dvi with a handy zoom+pan feature. Will not interpret PostScript specials, which are understood only by `dvips' (back to the compiler, object file, and now linker analogy :-) To view a file, do `xdvi file.dvi'. This comes with either TeX or X in most distributions. Either way, you've probably got one. If not, look in `ftp.x.org:/contrib/'. 4.4 xtex ======== Xtex is similar in purpose to xdvi. I have tried to build it under Linux and failed. It is available as: `ftp.x.org:/contrib/xtex-2.18.5.tar.z' 4.5 gxditview ============= Ditview produces a preview version of `troff' source using X fonts. `groff -TX100 -mandoc MAN PAGE' will run gxditview to show you a typeset version of the man page. `-TX75' is the same thing, but tiny. Most distributions don't have a working one at all. A good one comes with the source to `groff', which you might want to get anyway for the additional drivers (some distributions are missing some, including PostScript). `prep.ai.mit.edu:/pub/gnu/groff-XXXX.tar.z' 4.6 non-X previewing ==================== Ghostscript comes with pc video hardware drivers, but under un*x these are not a good thing. However, there are `gs' binaries around which will use the Linux VGA library (`svgalib'). The Ghostscript device for this is called linux, thus `gs -sDEVICE=linux file.ps' will show you an image of the PostScript. The environment variable `GSVGAMODE' is important for this. Set it to the nuber of the video mode you want, taken from the vga.h which comes with vgalib. If you need this driver, a patch to put in Linux svgalib is available from the printing mail server or as: ws105.zfn.uni-bremen.de:/pub/gs261-linuxdriver.sh ws105.zfn.uni-bremen.de:/pub/gs261-svgalib.tar.gz Another possibly different svgalib patch is found in: `ftp.cdrom.com:/pub/linux/misc' The plain vgalib driver is available on Sunsite. Texmgr is a program which will preview dvi under MGR. I don't beleive that it currently works under Linux MGR, but if it does, MGR uses sufficiently less memory and disk that this might be an attractive option for some. dvgt is a program which will preview dvi with Linux svgalib, or on one of several types of graphics terminals including vt, tek, or a PC with MS-Kermit. It is available on sunsite. 5 Ascii Translation ******************* These sections describe various programs which can generate plain ascii from some file formats. 5.1 from TeX ============ Lametex will generate ascii from TeX source. It is available as: `sunsite.unc.edu:/pub/Linux/apps/tex/lametex.tar.z' LaTeX is used by the Linux Doc Projext to generate text versions of their manuals. I don't know where to find it. 5.2 from dvi ============ `dvi2tty' is a program which will process dvi into text. Aparently, it will also make an effort at reproducing graphics as well. I do not know where to find it. 5.3 from PostScript =================== Ghostscript 2.6.1 comes with a script file which will use `gs' to extract just the text from a ps file, called `ps2ascii'. (*note PostScript., for information above for where it can be found). Further documentation is in the Ghostscript 2.6.1 distribution files `gs_2asc.ps' and `use.doc' 5.4 from troff ============== groff -Tascii or -Tlatin1 ... 5.5 from ascii/latin1 ===================== The GNU program `recode' handles conversion between various forms of straight text encoding, ie from Latin-1 to ASCII. This is available on prep.ai.mit.edu. -- Unless otherwise stated, Linux HOWTO documents are copyrighted by their respective authors. Linux HOWTO documents may be reproduced and distributed in whole or in part, in any medium physical or electronic, without permission of the author. Translations and derivative works are similarly permitted without express permission. Commercial redistribution is allowed and encouraged; however, the author would like to be notified of any such distributions. In short, we wish to promote dissemination of this information through as many channels as possible. However, we do wish to retain copyright on the HOWTO documents, and would like to be notified of any plans to redistribute the HOWTOs. If you have questions, please contact Matt Welsh, the Linux HOWTO coordinator, at mdw@sunsite.unc.edu.