summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>1998-11-09 12:24:13 (GMT)
committerH. Peter Anvin <hpa@zytor.com>1998-11-09 12:24:13 (GMT)
commit062ff2153324e49e7247da618b6e53d3827c3a62 (patch)
tree6d3f6a44251017e1c6fffc971fab97ed4d716bd5
downloadmagicfilter-master.zip
magicfilter-master.tar.gz
magicfilter-master.tar.bz2
magicfilter-master.tar.xz
Initial checkin of magicfilter; engine mostly working, filter filesHEADmaster
in disarray. Lots of work to do.
-rw-r--r--COPYING339
-rw-r--r--ChangeLog32
-rw-r--r--INSTALL181
-rw-r--r--Makefile.in118
-rw-r--r--QuickInst82
-rw-r--r--README33
-rw-r--r--acconfig.h5
-rw-r--r--aclocal.m497
-rw-r--r--config.h.in52
-rw-r--r--configure.in75
-rw-r--r--filters/Makefile.in78
-rw-r--r--filters/README10
-rw-r--r--filters/bj10e-filter.x38
-rw-r--r--filters/bj200-filter.x38
-rw-r--r--filters/cps300-filter.x5
-rw-r--r--filters/cps400-filter.x5
-rw-r--r--filters/cps600-filter.x5
-rw-r--r--filters/cpsonly300-filter.x4
-rw-r--r--filters/cpsonly400-filter.x4
-rw-r--r--filters/cpsonly600-filter.x4
-rw-r--r--filters/deskjet-filter.x38
-rw-r--r--filters/dj500-filter.x39
-rw-r--r--filters/dj500c-filter.x40
-rw-r--r--filters/dj550c-filter.x43
-rw-r--r--filters/epson9-filter.x41
-rw-r--r--filters/epson9c-filter.x41
-rw-r--r--filters/epsonlq-filter.x38
-rw-r--r--filters/epsonlqc-filter.x39
-rw-r--r--filters/filters.xh52
-rw-r--r--filters/filters1.h.in27
-rw-r--r--filters/filters2.h.in57
-rw-r--r--filters/genericps.xh33
-rw-r--r--filters/ibmpro-filter.x41
-rw-r--r--filters/jetp3852-filter.x38
-rw-r--r--filters/la50-filter.x41
-rw-r--r--filters/la75-filter.x41
-rw-r--r--filters/laserjet-filter.x38
-rw-r--r--filters/laserjetlo-filter.x38
-rw-r--r--filters/lbp8-filter.x38
-rw-r--r--filters/lj250-filter.x38
-rw-r--r--filters/ljet2p-filter.x38
-rw-r--r--filters/ljet2plo-filter.x38
-rw-r--r--filters/ljet3-filter.x38
-rw-r--r--filters/ljet4-filter.x41
-rw-r--r--filters/ljet4l-filter.x41
-rw-r--r--filters/ljet4m-filter.x36
-rw-r--r--filters/ljet4ml-filter.x35
-rw-r--r--filters/ljetplus-filter.x38
-rw-r--r--filters/ljetpluslo-filter.x38
-rw-r--r--filters/ln03-filter.x38
-rw-r--r--filters/m8510-filter.x41
-rwxr-xr-xfilters/mkfilterhin7
-rw-r--r--filters/necp6-filter.x38
-rw-r--r--filters/oki182-filter.x38
-rw-r--r--filters/pj-filter.x40
-rw-r--r--filters/pjxl-filter.x40
-rw-r--r--filters/pjxl300-filter.x40
-rw-r--r--filters/ps300-filter.x4
-rw-r--r--filters/ps400-filter.x4
-rw-r--r--filters/ps600-filter.x4
-rw-r--r--filters/psonly300-filter.x3
-rw-r--r--filters/psonly400-filter.x3
-rw-r--r--filters/psonly600-filter.x3
-rw-r--r--filters/r4081-filter.x38
-rw-r--r--filters/stdconv.xh348
-rw-r--r--filters/stdrejects.xh25
-rw-r--r--filters/tek4693-filter.x39
-rw-r--r--filters/tek4696-filter.x39
-rw-r--r--ghostprobe.c112
-rwxr-xr-xinstall-sh238
-rw-r--r--loadconfig.c208
-rw-r--r--magicfilter.c1240
-rw-r--r--magicfilter.h88
-rw-r--r--magicfilter.man.in438
-rw-r--r--mfpp.c1417
-rw-r--r--mfpp.h68
-rw-r--r--mfpp.y608
-rw-r--r--mfppact.c276
-rw-r--r--mfpplist.c115
-rw-r--r--mfppmain.c41
-rw-r--r--parseconfig.c445
-rw-r--r--plfilters/dj550c-filter.x25
-rw-r--r--plfilters/filters1.h28
-rw-r--r--plfilters/filters2.h58
-rwxr-xr-xplfilters/genmagicfilter26
-rw-r--r--plfilters/h2xh.pl15
-rw-r--r--plfilters/mfconfig.xh2
-rw-r--r--plfilters/mfconfig.xh.in57
-rw-r--r--plfilters/mfpaths.xh24
-rw-r--r--plfilters/stdconv.xh588
90 files changed, 9258 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..fb12037
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,32 @@
+1.2 Mar 17, 1996
+
+ * Most standard conversions moved to .xh include files in the
+ filters directory, will hopefully make maintenance of the filter
+ files a lot easier.
+ * Added fig file support.
+ * Added \004%! as a PostScript magic.
+ * LPRng support (UNTESTED!)
+ * Lots of suggestions were received, most got lost in a flood of
+ email. Sorry...
+
+1.1b Apr 4, 1995
+
+ * Portability improvements.
+ * Added filters for PostScript only printers; using (n)enscript.
+
+1.1a Mar 28, 1995
+
+ * Fixed bug in parseconfig.c that would cause perfectly legal config
+ files to abort with an "Invalid action" message.
+
+1.1 Mar 27, 1995
+
+ * Added prefix and suffix options to "cat" and "text" facilities.
+ * Fixed bugs in dj550c and ljet4 sample filters.
+ * Added another 37 different sample filters.
+ * Uses "autoconf" to automatically localize the sample filters to
+ fit your system. They should now be ready to drop in place.
+
+1.0 Mar 17, 1995
+
+ * Initial public release.
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..a2c8722
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,181 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..94cd013
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,118 @@
+# $Id$
+#
+# Makefile.in
+#
+# Makefile for the lpr/lpd magic filter
+#
+# Copyright 1995 Yggdrasil Computing, Inc
+# Copyright 1996-1998 H. Peter Anvin
+#
+
+#
+# Define the following to suit your taste
+#
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = ${exec_prefix}/bin
+mansec=8
+mandir = ${prefix}/man/man${mansec}
+
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+RM = rm -f
+MV = mv -f
+SED = sed
+YACC = @YACC@
+INSTALL = @INSTALL@
+INSTALL_EXEC = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+.SUFFIXES: .c .o .y
+
+#
+# These defines control the sending of mail notices to people who submit
+# bad jobs (PostScript to non-PS printers, or trying to print binaries.)
+#
+# This may not work if the hostname lpd knows about is not necessary a
+# valid mail address (for example, if you can submit print jobs from
+# non-mailer machines without MX records). If so, define -DNOMAIL.
+#
+# -DNOMAIL Disable sending of rejection mail notices
+# -DSENDMAIL="path" Where is your mail transport agent?
+# -DBANG_ADDRESS To send to "host!user" instead of "user@host"
+#
+# If <paths.h> exist and contains _PATH_SENDMAIL, it will be used unless
+# overridden here
+#
+SYSOPT=
+
+.c.o:
+ ${CC} ${CFLAGS} ${SYSOPT} -c $<
+
+.y.c:
+ ${YACC} $<
+ ${MV} y.tab.c $*.c
+
+.PHONY: all filters clean distclean install install_filters
+
+OBJS = magicfilter.o parseconfig.o loadconfig.o
+
+all: magicfilter magicfilter.man filters
+
+filters: filters/gsinfo.h # mfpp
+ cd filters; make
+
+install: magicfilter magicfilter.man
+ ${INSTALL_EXEC} magicfilter ${bindir}/magicfilter
+ ${INSTALL_DATA} magicfilter.man ${mandir}/magicfilter.${mansec}
+
+install_filters:
+ cd filters; make install
+
+clean:
+ -cd filters; make clean
+ -${RM} *.o magicfilter magicfilter.man ghostprobe mfpp
+
+distclean: clean
+ -cd filters; make distclean
+ -${RM} *~ *.s config.cache config.log config.status \#*\#
+ -${RM} config.h y.tab.c y.output Makefile
+
+spotless: distclean
+ -${RM} mfpp.c
+
+magicfilter: ${OBJS}
+ ${CC} ${LDFLAGS} -o magicfilter ${OBJS} ${LIBS}
+
+magicfilter.o: magicfilter.c magicfilter.h config.h
+
+parseconfig.o: parseconfig.c magicfilter.h config.h
+
+loadconfig.o: loadconfig.c magicfilter.h config.h
+
+filters/gsinfo.h: ghostprobe
+ ./ghostprobe > filters/gsinfo.h
+
+ghostprobe: ghostprobe.o
+ ${CC} ${LDFLAGS} -o ghostprobe ghostprobe.o ${LIBS}
+
+mfpp: mfpp.o mfppact.o mfppmain.o
+ ${CC} ${LDFLAGS} -o mfpp mfpp.o mfppact.o mfppmain.o ${LIBS}
+
+mfpp.o: mfpp.c mfpp.h
+
+mfppact.o: mfppact.c mfpp.h
+
+mfppmain.o: mfppmain.c mfpp.h
+
+mfpp.c: mfpp.y
+
+magicfilter.man: magicfilter.man.in
+ ${SED} -e "s:XXX_BINDIR_XXX:${bindir}:g" < magicfilter.man.in | \
+ ${SED} -e "s:///*:/:g" > magicfilter.man
diff --git a/QuickInst b/QuickInst
new file mode 100644
index 0000000..2ede0f7
--- /dev/null
+++ b/QuickInst
@@ -0,0 +1,82 @@
+Quick installation instructions:
+
+* Run "configure". If you want to put the files in any other directory
+ tree than /usr/local (i.e. /usr/local/bin, /usr/local/man) then call
+ it with the option --prefix=<directory-prefix>, for example:
+
+ ./configure --prefix=/usr
+
+ See the file INSTALL for more information.
+
+* Run "make".
+
+* Run "make install".
+
+* If you want to install all the sample printer filters (there are 40
+ of them in the 1.1 release) then do "make install_filters".
+ Otherwise pick the one(s) you want from the "filters" directory and
+ put them in the appropriate location. Make sure they are executable
+ (they can be considered "scripts", with magicfilter being the interpreter.)
+
+-----------------------------------------------------------------------------
+
+The following instructions apply only to systems using the BSD
+printing system. Linux and BSD-derived OSes all use the BSD printing
+system, some System V-based systems such as IRIX do as an option
+whereas others, such as Solaris, do not.
+
+If in doubt, check for the existence of the file /etc/printcap.
+
+NOTE: The standard BSD print daemon does *not* support filters for
+remote printers, hence the instructions below apply only to systems
+which have the printers physically attached. A version of lpd which
+does not have this problem is available as a part of the LPRng package
+from ftp://dickory.sdsu.edu/pub/LPRng/. To use filters with remote
+printers for LPRng, specify the "bqfilter" flag in /etc/printcap, for
+example:
+
+ # Remote HP LaserJet 4 (possibly connected via built-in Ethernet)
+ remoteprinter:\
+ :lp=:rm=printserver:rp=remoteprinter:\
+ :sd=/var/spool/lpd/remoteprinter:\
+ :bqfilter:mx#0:\
+ if=/usr/local/bin/ljet4-filter:
+
+-----------------------------------------------------------------------------
+
+* Edit your /etc/printcap file to contain a call to the appropriate
+ printer filter in the "if" entry of each local printer. This will
+ typically look something like this:
+
+ pencil|lp|PostScript|ljet4|HP LaserJet 4:\
+ :lp=/dev/lp1:sd=/var/spool/lpd/pencil:sh:mx#0:\
+ :if=/usr/local/bin/ljet4-filter:
+
+ crayon|dj550c|color|HP DeskJet 550C:\
+ :lp=/dev/lp2:sd=/var/spool/lpd/crayon:sh:mx#0:\
+ :if=/usr/local/bin/dj550c-filter:
+
+ Note the alias "lp" for the default (text) printer, and "PostScript"
+ for the preferred PostScript printer.
+
+ IMPORTANT: If you're on a really old version of UNIX which doesn't
+ support the so-called "#!-hack" for selecting an interpreter for
+ your filters, this form of installation does not work. Instead, you
+ need to make your /etc/printcap file look something like this:
+
+ pencil|lp|PostScript|ljet4|HP LaserJet 4:\
+ :lp=/dev/lp1:sd=/var/spool/lpd/pencil:sh:mx#0:\
+ :if=/usr/local/bin/magicfilter:\
+ :af=/usr/local/bin/ljet4-filter:
+
+ To test if your OS supports the #!-hack, type at the command line:
+
+ /usr/local/bin/XXXX-filter < /dev/null
+
+ ... where XXXX-filter is any installed magic filter. If you get an
+ error message, your OS does *not* support the #!-hack.
+
+ Linux, all BSD-derived OSes and System V R3 and later all support
+ the #!-hack.
+
+* Kill and restart lpd. Your printer filter should now be working.
diff --git a/README b/README
new file mode 100644
index 0000000..8e0e8a3
--- /dev/null
+++ b/README
@@ -0,0 +1,33 @@
+ MAGICFILTER v 1.1
+
+ by
+
+ H. Peter Anvin
+ <hpa@zytor.com>
+
+===> Read the file QuickInst for quick installation instructions <===
+
+
+MAGICFILTER is a customizable, extensible automatic printer filter.
+Although written for Linux, it should work on any UNIX system which
+has an ANSI C compiler.
+
+If you use MAGICFILTER and find it useful, I would appreciate an email
+note from you. If you are using it on a type of printer that I do not
+have, I would also appreciate a copy of your configuration file for
+inclusion in future versions. If you have suggestions for
+improvement, I would love to hear them as well.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
diff --git a/acconfig.h b/acconfig.h
new file mode 100644
index 0000000..76ee21d
--- /dev/null
+++ b/acconfig.h
@@ -0,0 +1,5 @@
+/* define if ditroff works as expected */
+#undef DITROFF_WORKS
+
+/* define if zcat is really gzip */
+#undef ZCAT_IS_GZIP
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..ab61fe7
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,97 @@
+dnl --------------------------------------------------------------------------
+dnl MF_PATH_INCLUDE:
+dnl
+dnl Like AC_PATH_PROGS, but add to the .h file as well
+dnl --------------------------------------------------------------------------
+AC_DEFUN(MF_PATH_INCLUDE,
+[AC_PATH_PROGS($1,$2)
+if test -n "$$1"; then
+ AC_DEFINE(HAVE_$1)
+ AC_DEFINE_UNQUOTED(PATH_$1, "$$1")
+fi])
+
+dnl --------------------------------------------------------------------------
+dnl MF_FILE_R:
+dnl
+dnl Look for a file entry and define a variable if exists and is readable
+dnl Redirect stdin in case we're checking for /dev/stdin
+dnl --------------------------------------------------------------------------
+AC_DEFUN(MF_FILE_R,
+[AC_MSG_CHECKING(for $2)
+if test -r "$2" < /dev/null; then
+ AC_DEFINE(HAVE_$1)
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi])
+
+dnl --------------------------------------------------------------------------
+dnl MF_FILE_W:
+dnl
+dnl Look for a file entry and define a variable if exists and is writeable
+dnl Redirect stdout, stderr in case we're checking for /dev/stdout,err
+dnl --------------------------------------------------------------------------
+AC_DEFUN(MF_FILE_W,
+[AC_MSG_CHECKING(for $2)
+if test -w "$2" > /dev/null 2>&1; then
+ AC_DEFINE(HAVE_$1)
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi])
+
+dnl --------------------------------------------------------------------------
+dnl MF_PROG_GNU_ZCAT:
+dnl
+dnl Check to see if zcat is really gzip
+dnl --------------------------------------------------------------------------
+AC_DEFUN(MF_PROG_GNU_ZCAT,
+[AC_MSG_CHECKING(whether zcat is really gzip)
+
+AC_CACHE_VAL(mf_cv_prog_gnu_zcat,
+[if echo -e "\37\213\10\10\273\31\152\57\4\3\170\0\3\0\0\0\0\0\0\0\0\0\c"| $1 \
+ 2>&1 >/dev/null || grep "GNU" $1 2>&1 >/dev/null
+then
+ mf_cv_prog_gnu_zcat=yes
+else
+ mf_cv_prog_gnu_zcat=no
+fi])
+
+if test "$mf_cv_prog_gnu_zcat" = "yes"
+then
+ AC_DEFINE(ZCAT_IS_GZIP)
+fi
+AC_MSG_RESULT($mf_cv_prog_gnu_zcat)
+])
+
+dnl --------------------------------------------------------------------------
+dnl MF_PROG_DITROFF:
+dnl
+dnl Check to see if ditroff works
+dnl --------------------------------------------------------------------------
+AC_DEFUN(MF_PROG_DITROFF,
+[AC_MSG_CHECKING(whether ditroff works)
+
+AC_CACHE_VAL(mf_cv_prog_ditroff,
+[if cat << EOF | $1 2>&1 >/dev/null
+x T ps
+x res 72000 1 1
+x init
+p1
+x trailer
+V792000
+x stop
+EOF
+then
+ mf_cv_prog_ditroff=yes
+else
+ mf_cv_prog_ditroff=no
+fi])
+
+if test "$mf_cv_prog_ditroff" = "yes"
+then
+ AC_DEFINE(DITROFF_WORKS)
+fi
+AC_MSG_RESULT($mf_cv_prog_ditroff)
+])
+
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..ac9cde9
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,52 @@
+/* config.h.in */
+
+/* Define if you are using MINIX. */
+#undef _MINIX
+
+/* Define if necessary to use POSIX facilities on your system. */
+#undef _POSIX_SOURCE
+#undef _POSIX_1_SOURCE
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef pid_t
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you have the dup2 function. */
+#undef HAVE_DUP2
+
+/* Define if you have the tmpnam function. */
+#undef HAVE_TMPNAM
+
+/* Define if you have the waitpid function. */
+#undef HAVE_WAITPID
+
+/* Define if you have the wait4 function. */
+#undef HAVE_WAIT4
+
+/* Define if you have the unsetenv function. */
+#undef HAVE_UNSETENV
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have a sendmail-compatible mailer. */
+#undef HAVE_SENDMAIL
+#undef PATH_SENDMAIL
+
+/* Define if you have Ghostscript (used by ghostprobe). */
+#undef HAVE_GHOSTSCRIPT
+#undef PATH_GHOSTSCRIPT
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..7a253e6
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,75 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(magicfilter.c)
+
+AC_CONFIG_HEADER(config.h filters/filters1.h filters/filters2.h)
+
+dnl Figure out the C compiler
+AC_PROG_CC
+AC_MINIX
+AC_AIX
+AC_ISC_POSIX
+
+dnl Check for programs used by makefiles
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_YACC
+
+dnl Check for programs used in filters
+MF_PATH_INCLUDE(GHOSTSCRIPT, gs)
+MF_PATH_INCLUDE(PDF2PS, pdf2ps)
+MF_PATH_INCLUDE(GROG, grog)
+MF_PATH_INCLUDE(GROFF, groff)
+MF_PATH_INCLUDE(DITROFF, gtroff ditroff troff)
+MF_PATH_INCLUDE(GROPS, grops)
+MF_PATH_INCLUDE(GRODVI, grodvi)
+MF_PATH_INCLUDE(GROTTY, grotty)
+MF_PATH_INCLUDE(GROLJ4, grolj4)
+MF_PATH_INCLUDE(GZIP, gzip gunzip gzcat)
+MF_PATH_INCLUDE(ZCAT, zcat)
+MF_PATH_INCLUDE(UNCOMPRESS, uncompress)
+MF_PATH_INCLUDE(DVIPS, dvips)
+MF_PATH_INCLUDE(PNMTOPS, pnmtops)
+MF_PATH_INCLUDE(GIFTOPPM, giftopnm giftoppm)
+MF_PATH_INCLUDE(DJPEG, djpeg)
+MF_PATH_INCLUDE(PNGTOPNM, pngtopnm)
+MF_PATH_INCLUDE(SGITOPNM, sgitopnm)
+MF_PATH_INCLUDE(TOPS, tops)
+MF_PATH_INCLUDE(SGITOPS, sgitops)
+MF_PATH_INCLUDE(TIFFTOPNM, tifftopnm)
+MF_PATH_INCLUDE(BMPTOPPM, bmptopnm bmptoppm)
+MF_PATH_INCLUDE(RASTTOPNM, rasttopnm)
+MF_PATH_INCLUDE(NENSCRIPT, nenscript enscript)
+MF_PATH_INCLUDE(A2X, a2x)
+MF_PATH_INCLUDE(A2PS, a2ps)
+MF_PATH_INCLUDE(FIG2DEV, fig2dev)
+
+dnl Check to see if zcat is gzip
+MF_PROG_GNU_ZCAT($ZCAT)
+
+dnl Check to see if ditroff works
+MF_PROG_DITROFF($DITROFF)
+
+dnl Look for sendmail or mail for sending mail to users
+mf_save_path="$PATH"
+PATH=$PATH:/usr/libexec:/usr/sbin:/usr/lib:/usr/etc:/etc:/bin:/usr/ucb
+MF_PATH_INCLUDE(SENDMAIL, sendmail smail mail Mail)
+PATH="$mf_save_path"
+
+dnl Check for header files
+AC_CHECK_HEADERS(memory.h)
+AC_CHECK_HEADERS(paths.h)
+AC_CHECK_HEADERS(stdlib.h)
+AC_CHECK_HEADERS(unistd.h)
+AC_HEADER_SYS_WAIT
+
+dnl Check for missing C things
+AC_C_CONST
+AC_TYPE_PID_T
+AC_CHECK_FUNCS(dup2)
+AC_CHECK_FUNCS(tmpnam)
+AC_CHECK_FUNCS(waitpid)
+AC_CHECK_FUNCS(wait4)
+AC_CHECK_FUNCS(unsetenv)
+
+dnl Write Makefile
+AC_OUTPUT(Makefile filters/Makefile)
diff --git a/filters/Makefile.in b/filters/Makefile.in
new file mode 100644
index 0000000..cc3ca53
--- /dev/null
+++ b/filters/Makefile.in
@@ -0,0 +1,78 @@
+#
+# Makefile for printer filters
+#
+# The printer filters are localized for this system
+#
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@ -I.
+SED = sed
+RM = rm -f
+LN = @LN_S@
+CHMOD = chmod
+MFPP = ../mfpp
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = ${exec_prefix}/bin
+INSTALL = @INSTALL@
+INSTALL_EXEC = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+FILTERS= bj10e-filter laserjet-filter m8510-filter \
+ bj200-filter laserjetlo-filter necp6-filter \
+ deskjet-filter lbp8-filter oki182-filter \
+ dj500-filter lj250-filter pj-filter \
+ dj500c-filter ljet2p-filter pjxl-filter \
+ dj550c-filter ljet2plo-filter pjxl300-filter \
+ epson9-filter ljet3-filter ps300-filter \
+ epson9c-filter ljet4-filter ps400-filter \
+ epsonlq-filter ljet4l-filter ps600-filter \
+ epsonlqc-filter ljet4m-filter r4081-filter \
+ ibmpro-filter ljet4ml-filter tek4693-filter \
+ jetp3852-filter ljetplus-filter tek4696-filter \
+ la50-filter ljetpluslo-filter \
+ la75-filter ln03-filter \
+ psonly300-filter psonly400-filter psonly600-filter \
+ cps300-filter cps400-filter cps600-filter \
+ cpsonly300-filter cpsonly400-filter cpsonly600-filter
+
+.SUFFIXES:
+.SUFFIXES: .x .h .xh
+
+.x:
+ ${MFPP} $< > $*
+ ${CHMOD} a+x $*
+
+all: ${FILTERS}
+
+install: all
+ for filter in ${FILTERS}; do \
+ ${INSTALL_EXEC} $$filter ${bindir}/$$filter; \
+ done
+
+clean:
+ -${RM} *-filter
+distclean: clean
+ -${RM} *~ *.tmp Makefile filters1.h filters2.h gsinfo.h
+
+gsinfo.h: ../config.h
+ cd ..; make filters/gsinfo.h; cd filters
+
+# The dependencies the following defines are a little overly restrictive,
+# but get the job done
+depend:
+ head -n `grep -n '^# DEPENDENCIES' Makefile | cut -d':' -f1 ` \
+ Makefile > Makefile.tmp
+ for xfile in *.x; do \
+ echo $${xfile}: *.xh filters1.h filters2.h >> Makefile.tmp; \
+ done
+ mv Makefile.tmp Makefile
+
+idepend:
+ head -n `grep -n '^# DEPENDENCIES' Makefile.in | cut -d':' -f1 ` \
+ Makefile.in > Makefile.in.tmp
+ for xfile in *.x; do \
+ echo $${xfile}: *.xh filters1.h filters2.h >> Makefile.in.tmp; \
+ done
+ mv Makefile.in.tmp Makefile.in
+
+# DEPENDENCIES -- do not delete this line --
diff --git a/filters/README b/filters/README
new file mode 100644
index 0000000..e7e87ea
--- /dev/null
+++ b/filters/README
@@ -0,0 +1,10 @@
+IMPORTANT: The only filters which have been tested are the dj500,
+dj550c and ljet4m filters, since those are the only printer types I
+use. Any additional files are untested, even if they do not
+explicitly say so. I would like information if they work properly or
+not; please send me email at <peter.anvin@linux.org> if you are using
+any of the other sample filters.
+
+Thanks,
+
+ /hpa \ No newline at end of file
diff --git a/filters/bj10e-filter.x b/filters/bj10e-filter.x
new file mode 100644
index 0000000..b9fc4d7
--- /dev/null
+++ b/filters/bj10e-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for Canon BubbleJet 10E
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 360
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r360 -sDEVICE=bj10e -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/bj200-filter.x b/filters/bj200-filter.x
new file mode 100644
index 0000000..081dfe0
--- /dev/null
+++ b/filters/bj200-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for Canon BubbleJet 200
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 360
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r360 -sDEVICE=bj200 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/cps300-filter.x b/filters/cps300-filter.x
new file mode 100644
index 0000000..c63b087
--- /dev/null
+++ b/filters/cps300-filter.x
@@ -0,0 +1,5 @@
+# $Id$
+%define DPI 300
+%define NATIVE_TEXT 1
+%define IS_COLOR 1
+%include <genericps.mh>
diff --git a/filters/cps400-filter.x b/filters/cps400-filter.x
new file mode 100644
index 0000000..a45ab1a
--- /dev/null
+++ b/filters/cps400-filter.x
@@ -0,0 +1,5 @@
+# $Id$
+%define DPI 400
+%define NATIVE_TEXT 1
+%define IS_COLOR 1
+%include <genericps.mh>
diff --git a/filters/cps600-filter.x b/filters/cps600-filter.x
new file mode 100644
index 0000000..16580d3
--- /dev/null
+++ b/filters/cps600-filter.x
@@ -0,0 +1,5 @@
+# $Id$
+%define DPI 600
+%define NATIVE_TEXT 1
+%define IS_COLOR 1
+%include <genericps.mh>
diff --git a/filters/cpsonly300-filter.x b/filters/cpsonly300-filter.x
new file mode 100644
index 0000000..310fac8
--- /dev/null
+++ b/filters/cpsonly300-filter.x
@@ -0,0 +1,4 @@
+# $Id$
+%define DPI 300
+%define IS_COLOR 1
+%include <genericps.mh>
diff --git a/filters/cpsonly400-filter.x b/filters/cpsonly400-filter.x
new file mode 100644
index 0000000..5eade52
--- /dev/null
+++ b/filters/cpsonly400-filter.x
@@ -0,0 +1,4 @@
+# $Id$
+%define DPI 400
+%define IS_COLOR 1
+%include <genericps.mh>
diff --git a/filters/cpsonly600-filter.x b/filters/cpsonly600-filter.x
new file mode 100644
index 0000000..1b6a34c
--- /dev/null
+++ b/filters/cpsonly600-filter.x
@@ -0,0 +1,4 @@
+# $Id$
+%define DPI 600
+%define IS_COLOR 1
+%include <genericps.mh>
diff --git a/filters/deskjet-filter.x b/filters/deskjet-filter.x
new file mode 100644
index 0000000..c7a9c3d
--- /dev/null
+++ b/filters/deskjet-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for HP DeskJet pre-500 series
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=deskjet -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/dj500-filter.x b/filters/dj500-filter.x
new file mode 100644
index 0000000..20d9350
--- /dev/null
+++ b/filters/dj500-filter.x
@@ -0,0 +1,39 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for HP DeskJet 500 series B/W printers; including
+# DJ 500C with black ink cartridge installed
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=djet500 -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/dj500c-filter.x b/filters/dj500c-filter.x
new file mode 100644
index 0000000..f014728
--- /dev/null
+++ b/filters/dj500c-filter.x
@@ -0,0 +1,40 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for HP DeskJet 500 series color printers with
+# only CMY cartridge installed
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+%define IS_COLOR 1
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=cdj500 -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/dj550c-filter.x b/filters/dj550c-filter.x
new file mode 100644
index 0000000..980696f
--- /dev/null
+++ b/filters/dj550c-filter.x
@@ -0,0 +1,43 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for HP DeskJet 500 series color printers with
+# both black and CMY cartridges installed
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+%define IS_COLOR 1
+/*
+ * PostScript, PDF
+ */
+%ifdef GS_PS
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=cdj550 -sOutputFile=- -
+%endif
+%ifdef GS_LANG_PDF
+%define HANDLE_PDF ffilter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=cdj550 -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/epson9-filter.x b/filters/epson9-filter.x
new file mode 100644
index 0000000..61681fe
--- /dev/null
+++ b/filters/epson9-filter.x
@@ -0,0 +1,41 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for 9-pin Epson (or compatible) printers
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ * DPI is set to the lowest common denominator of XDPI and YDPI
+ */
+%define XDPI 120
+%define YDPI 72
+%define DPI 360
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r120x72 -sDEVICE=epson -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/epson9c-filter.x b/filters/epson9c-filter.x
new file mode 100644
index 0000000..deb6bcb
--- /dev/null
+++ b/filters/epson9c-filter.x
@@ -0,0 +1,41 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for 9-pin Epson (or compatible) color printers
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ * DPI is set to the lowest common denominator of XDPI and YDPI
+ */
+%define XDPI 120
+%define YDPI 72
+%define DPI 360
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r120x72 -sDEVICE=epsonc -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/epsonlq-filter.x b/filters/epsonlq-filter.x
new file mode 100644
index 0000000..b479bab
--- /dev/null
+++ b/filters/epsonlq-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for Epson LQ series printers
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 180
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r180 -sDEVICE=epson -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/epsonlqc-filter.x b/filters/epsonlqc-filter.x
new file mode 100644
index 0000000..cffa070
--- /dev/null
+++ b/filters/epsonlqc-filter.x
@@ -0,0 +1,39 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for Epson LQ series color printers
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 180
+%define IS_COLOR 1
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r180 -sDEVICE=epsonc -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/filters.xh b/filters/filters.xh
new file mode 100644
index 0000000..cb4d5f5
--- /dev/null
+++ b/filters/filters.xh
@@ -0,0 +1,52 @@
+% $Id$
+%
+% Header file for filters - included at top of all filters
+%
+% --------------------------------------------------------------------------
+%
+% Information from configure
+%
+%cinclude <filters1.h>
+%cinclude <filters2.h>
+%
+% Ghostscript configuration, if applicable
+%
+%if HAVE_GHOSTSCRIPT
+ %cinclude <gsinfo.h>
+%endif
+%if GS_LANG_PostScript || GS_LANG_PostScriptLevel1 || GS_LANG_PostScriptLevel2
+ % Ghostscript options for PostScript are too many, too long
+ % Make it easier on ourselves
+ %define GS_PS
+%endif
+%
+% Figure out how to deal with compress and gzip files
+%
+%if HAVE_GZIP
+ %define ZCAT: PATH_GZIP -cdq
+ %define GZCAT: PATH_GZIP -cdq
+%elif HAVE_ZCAT
+ %define ZCAT: PATH_ZCAT
+ %if ZCAT_IS_GZIP
+ %define GZCAT: PATH_ZCAT
+ %endif
+%elif HAVE_UNCOMPRESS
+ %define ZCAT: PATH_UNCOMPRESS -c
+%endif
+%
+% See if we have a way to access stdin and stdout as file descriptors
+%
+%if HAVE_DEV_STDIN
+ %define STDIN: /dev/stdin
+%elif HAVE_DEV_FD_0
+ %define STDIN: /dev/fd/0
+%elif HAVE_PROC_SELF_FD_0
+ %define STDIN: /proc/self/fd/0
+%endif
+%if HAVE_DEV_STDOUT
+ %define STDOUT: /dev/stdout
+%elif HAVE_DEV_FD_1
+ %define STDOUT: /dev/fd/1
+%elif HAVE_PROC_SELF_FD_1
+ %define STDOUT: /proc/self/fd/1
+%endif
diff --git a/filters/filters1.h.in b/filters/filters1.h.in
new file mode 100644
index 0000000..4dfeac1
--- /dev/null
+++ b/filters/filters1.h.in
@@ -0,0 +1,27 @@
+/*
+ * Fill-in-the-blank file for configure; included from filters.xh
+ *
+ * Note that only #define statements in this file are actually processed!
+ */
+
+/* define if ditroff works as expected */
+#undef DITROFF_WORKS
+
+/* define if zcat is really gzip */
+#undef ZCAT_IS_GZIP
+
+/* define if we have a way to access the standard file handles through
+ a pathname */
+
+/* /dev/stdin, /dev/stdout (FSSTND compliant Linux) */
+#undef HAVE_DEV_STDIN
+#undef HAVE_DEV_STDOUT
+
+/* /dev/fd/0, /dev/fd/1 (System V) */
+#undef HAVE_DEV_FD_0
+#undef HAVE_DEV_FD_1
+
+/* /proc/self/fd/0, /proc/self/fd/1 (Linux, even if noncompliant)
+ The path name is way ugly, though... */
+#undef HAVE_PROC_SELF_FD_0
+#undef HAVE_PROC_SELF_FD_1
diff --git a/filters/filters2.h.in b/filters/filters2.h.in
new file mode 100644
index 0000000..0cee3e2
--- /dev/null
+++ b/filters/filters2.h.in
@@ -0,0 +1,57 @@
+/* filters2.h.in: This file was automatically generated by mkfilterhin */
+#undef HAVE_GHOSTSCRIPT
+#undef PATH_GHOSTSCRIPT
+#undef HAVE_PDF2PS
+#undef PATH_PDF2PS
+#undef HAVE_GROG
+#undef PATH_GROG
+#undef HAVE_GROFF
+#undef PATH_GROFF
+#undef HAVE_DITROFF
+#undef PATH_DITROFF
+#undef HAVE_GROPS
+#undef PATH_GROPS
+#undef HAVE_GRODVI
+#undef PATH_GRODVI
+#undef HAVE_GROTTY
+#undef PATH_GROTTY
+#undef HAVE_GROLJ4
+#undef PATH_GROLJ4
+#undef HAVE_GZIP
+#undef PATH_GZIP
+#undef HAVE_ZCAT
+#undef PATH_ZCAT
+#undef HAVE_UNCOMPRESS
+#undef PATH_UNCOMPRESS
+#undef HAVE_DVIPS
+#undef PATH_DVIPS
+#undef HAVE_PNMTOPS
+#undef PATH_PNMTOPS
+#undef HAVE_GIFTOPPM
+#undef PATH_GIFTOPPM
+#undef HAVE_DJPEG
+#undef PATH_DJPEG
+#undef HAVE_PNGTOPNM
+#undef PATH_PNGTOPNM
+#undef HAVE_SGITOPNM
+#undef PATH_SGITOPNM
+#undef HAVE_TOPS
+#undef PATH_TOPS
+#undef HAVE_SGITOPS
+#undef PATH_SGITOPS
+#undef HAVE_TIFFTOPNM
+#undef PATH_TIFFTOPNM
+#undef HAVE_BMPTOPPM
+#undef PATH_BMPTOPPM
+#undef HAVE_RASTTOPNM
+#undef PATH_RASTTOPNM
+#undef HAVE_NENSCRIPT
+#undef PATH_NENSCRIPT
+#undef HAVE_A2X
+#undef PATH_A2X
+#undef HAVE_A2PS
+#undef PATH_A2PS
+#undef HAVE_FIG2DEV
+#undef PATH_FIG2DEV
+#undef HAVE_SENDMAIL
+#undef PATH_SENDMAIL
diff --git a/filters/genericps.xh b/filters/genericps.xh
new file mode 100644
index 0000000..5a38116
--- /dev/null
+++ b/filters/genericps.xh
@@ -0,0 +1,33 @@
+% $Id$
+%include <filters.xh>
+#
+%if IS_COLOR
+# Magic filter setup file for DPI dpi color PostScript printers
+%else
+# Magic filter setup file for DPI dpi generic PostScript printers
+%endif
+%if NATIVE_TEXT
+# with native capability to print ASCII text
+%endif
+#
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+#
+%
+% PostScript
+%
+%define NATIVE_PS
+%
+% Text
+%
+%if NATIVE_TEXT
+%define HANDLE_TEXT: text
+%endif
+
+%include <stdconv.xh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ibmpro-filter.x b/filters/ibmpro-filter.x
new file mode 100644
index 0000000..1ca569e
--- /dev/null
+++ b/filters/ibmpro-filter.x
@@ -0,0 +1,41 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the IBM ProPrinter
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ * DPI is set to the lowest common denominator of XDPI and YDPI
+ */
+%define XDPI 120
+%define YDPI 72
+%define DPI 360
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r120x72 -sDEVICE=ibmpro -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/jetp3852-filter.x b/filters/jetp3852-filter.x
new file mode 100644
index 0000000..1f36b53
--- /dev/null
+++ b/filters/jetp3852-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for IBM JetPrinter 3852
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 84
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r84 -sDEVICE=jetp3852 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/la50-filter.x b/filters/la50-filter.x
new file mode 100644
index 0000000..de468a4
--- /dev/null
+++ b/filters/la50-filter.x
@@ -0,0 +1,41 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the DEC LA-50 printer
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ * DPI is set to the lowest common denominator of XDPI and YDPI
+ */
+%define XDPI 144
+%define YDPI 72
+%define DPI 144
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r144x72 -sDEVICE=la50 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/la75-filter.x b/filters/la75-filter.x
new file mode 100644
index 0000000..e4d0862
--- /dev/null
+++ b/filters/la75-filter.x
@@ -0,0 +1,41 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the DEC LA-75 printer
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ * DPI is set to the lowest common denominator of XDPI and YDPI
+ */
+%define XDPI 144
+%define YDPI 72
+%define DPI 144
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r144x72 -sDEVICE=la75 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/laserjet-filter.x b/filters/laserjet-filter.x
new file mode 100644
index 0000000..07a1000
--- /dev/null
+++ b/filters/laserjet-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for HP LaserJet with 1.5 Mb or more RAM
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=laserjet -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/laserjetlo-filter.x b/filters/laserjetlo-filter.x
new file mode 100644
index 0000000..8a41f92
--- /dev/null
+++ b/filters/laserjetlo-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for HP LaserJet with less than 1.5 Mb RAM
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 150
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r150 -sDEVICE=laserjet -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/lbp8-filter.x b/filters/lbp8-filter.x
new file mode 100644
index 0000000..a04cf91
--- /dev/null
+++ b/filters/lbp8-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the Canon LBP-8II laser printer
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=lbp8 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/lj250-filter.x b/filters/lj250-filter.x
new file mode 100644
index 0000000..4c0630d
--- /dev/null
+++ b/filters/lj250-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the DEC LJ250
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 180
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r180 -sDEVICE=lj250 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ljet2p-filter.x b/filters/ljet2p-filter.x
new file mode 100644
index 0000000..1e9f8fe
--- /dev/null
+++ b/filters/ljet2p-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for LaserJet IID/IIP with 1.5 Mb or more RAM
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=ljet2p -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ljet2plo-filter.x b/filters/ljet2plo-filter.x
new file mode 100644
index 0000000..15e4ffc
--- /dev/null
+++ b/filters/ljet2plo-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for LaserJet IID/IIP with less than 1.5 Mb RAM
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 150
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r150 -sDEVICE=ljet2p -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ljet3-filter.x b/filters/ljet3-filter.x
new file mode 100644
index 0000000..92d2fcf
--- /dev/null
+++ b/filters/ljet3-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for LaserJet III series
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=ljet3 -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ljet4-filter.x b/filters/ljet4-filter.x
new file mode 100644
index 0000000..7c64ff8
--- /dev/null
+++ b/filters/ljet4-filter.x
@@ -0,0 +1,41 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for 600 DPI LaserJet 4 series without PostScript
+# (i.e. LJ 4P, 4, 4+, 4V or 4Si without PostScript option installed)
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 600
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r600 -sDEVICE=ljet4 -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL5E cat
+%define HANDLE_PCL cat
+%define HANDLE_PJL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ljet4l-filter.x b/filters/ljet4l-filter.x
new file mode 100644
index 0000000..10b1ae4
--- /dev/null
+++ b/filters/ljet4l-filter.x
@@ -0,0 +1,41 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for 300 DPI LaserJet 4 series without PostScript
+# (i.e. LJ 4L)
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=ljet4 -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL5E cat
+%define HANDLE_PCL cat
+%define HANDLE_PJL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ljet4m-filter.x b/filters/ljet4m-filter.x
new file mode 100644
index 0000000..c1ad295
--- /dev/null
+++ b/filters/ljet4m-filter.x
@@ -0,0 +1,36 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for 600 DPI LaserJet 4 series with PostScript
+# (i.e. LJ 4MP, 4M, 4M+, 4MV or 4SiMX or 4P, 4, 4+, 4V or 4Si with PostScript
+# option installed).
+#
+# This file has been automatically adapted to your system.
+#
+/*
+ * Printer resolution
+ */
+%define DPI 600
+/*
+ * PostScript
+ */
+%define NATIVE_PS 1
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL5E cat
+%define HANDLE_PCL cat
+%define HANDLE_PJL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ljet4ml-filter.x b/filters/ljet4ml-filter.x
new file mode 100644
index 0000000..8f0426f
--- /dev/null
+++ b/filters/ljet4ml-filter.x
@@ -0,0 +1,35 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for 300 DPI LaserJet 4 series with PostScript
+# (i.e. LJ 4ML).
+#
+# This file has been automatically adapted to your system.
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%define NATIVE_PS 1
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL5E cat
+%define HANDLE_PCL cat
+%define HANDLE_PJL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ljetplus-filter.x b/filters/ljetplus-filter.x
new file mode 100644
index 0000000..2b22256
--- /dev/null
+++ b/filters/ljetplus-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for HP Laserjet + or II with 1.5 Mb or more RAM
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=ljetplus -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ljetpluslo-filter.x b/filters/ljetpluslo-filter.x
new file mode 100644
index 0000000..32cebdc
--- /dev/null
+++ b/filters/ljetpluslo-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for HP Laserjet + or II with less than 1.5 Mb RAM
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 150
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r150 -sDEVICE=ljetplus -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ln03-filter.x b/filters/ln03-filter.x
new file mode 100644
index 0000000..3729d4e
--- /dev/null
+++ b/filters/ln03-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the DEC LN-03 printer
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=ln03 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/m8510-filter.x b/filters/m8510-filter.x
new file mode 100644
index 0000000..54dc8c0
--- /dev/null
+++ b/filters/m8510-filter.x
@@ -0,0 +1,41 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the C.Itoh M8510 printer
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ * DPI is set to the lowest common denominator of XDPI and YDPI
+ */
+%define XDPI 160
+%define YDPI 144
+%define DPI 1440
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r160x144 -sDEVICE=epson -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/mkfilterhin b/filters/mkfilterhin
new file mode 100755
index 0000000..015f689
--- /dev/null
+++ b/filters/mkfilterhin
@@ -0,0 +1,7 @@
+#!/bin/sh
+file=filters2.h.in
+echo "/* $file: This file was automatically generated by mkfilterhin */" \
+ > $file
+grep 'MF_PATH_INCLUDE' ../configure.in | \
+ sed -e 's/MF_PATH_INCLUDE(/#undef HAVE_/' \
+ -e 's/,.*$//' -e 'p' -e 's/HAVE_/PATH_/' >> $file
diff --git a/filters/necp6-filter.x b/filters/necp6-filter.x
new file mode 100644
index 0000000..1fa06de
--- /dev/null
+++ b/filters/necp6-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the NEC P6, P6+ and P60 printers
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 360
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r360 -sDEVICE=necp6 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/oki182-filter.x b/filters/oki182-filter.x
new file mode 100644
index 0000000..7a7451f
--- /dev/null
+++ b/filters/oki182-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the OKI 182
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 144
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r144 -sDEVICE=oki182 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/pj-filter.x b/filters/pj-filter.x
new file mode 100644
index 0000000..2a92473
--- /dev/null
+++ b/filters/pj-filter.x
@@ -0,0 +1,40 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the HP PaintJet
+# THIS FILE IS UNTESTED!
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 180
+%define IS_COLOR 1
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r180 -sDEVICE=pj -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/pjxl-filter.x b/filters/pjxl-filter.x
new file mode 100644
index 0000000..5b5d261
--- /dev/null
+++ b/filters/pjxl-filter.x
@@ -0,0 +1,40 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the HP PaintJet XL
+# THIS FILE IS UNTESTED!
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 180
+%define IS_COLOR 1
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r180 -sDEVICE=pjxl -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/pjxl300-filter.x b/filters/pjxl300-filter.x
new file mode 100644
index 0000000..d0656cd
--- /dev/null
+++ b/filters/pjxl300-filter.x
@@ -0,0 +1,40 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the HP PaintJet XL 300
+# THIS FILE IS UNTESTED!
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+%define IS_COLOR 1
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=pjxl300 -sOutputFile=- -
+%endif
+/*
+ * PCL, PJL
+ */
+%define HANDLE_PCL cat
+/*
+ * Text
+ */
+%define HANDLE_TEXT cat \eE\e&k2G\e(0N \eE
+%define LATIN1_OK 1
+
+%include <stdconv.mh>
+
+# wild guess: PCL control codes start with <ESC>
+0 \033 HANDLE_PCL
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/ps300-filter.x b/filters/ps300-filter.x
new file mode 100644
index 0000000..abbab39
--- /dev/null
+++ b/filters/ps300-filter.x
@@ -0,0 +1,4 @@
+# $Id$
+%define DPI: 300
+%define NATIVE_TEXT
+%include <genericps.xh>
diff --git a/filters/ps400-filter.x b/filters/ps400-filter.x
new file mode 100644
index 0000000..93c1a13
--- /dev/null
+++ b/filters/ps400-filter.x
@@ -0,0 +1,4 @@
+# $Id$
+%define DPI 400
+%define NATIVE_TEXT 1
+%include <genericps.mh>
diff --git a/filters/ps600-filter.x b/filters/ps600-filter.x
new file mode 100644
index 0000000..54de7f4
--- /dev/null
+++ b/filters/ps600-filter.x
@@ -0,0 +1,4 @@
+# $Id$
+%define DPI 600
+%define NATIVE_TEXT 1
+%include <genericps.mh>
diff --git a/filters/psonly300-filter.x b/filters/psonly300-filter.x
new file mode 100644
index 0000000..ea50993
--- /dev/null
+++ b/filters/psonly300-filter.x
@@ -0,0 +1,3 @@
+# $Id$
+%define DPI 300
+%include <genericps.mh>
diff --git a/filters/psonly400-filter.x b/filters/psonly400-filter.x
new file mode 100644
index 0000000..316c4fe
--- /dev/null
+++ b/filters/psonly400-filter.x
@@ -0,0 +1,3 @@
+# $Id$
+%define DPI 400
+%include <genericps.mh>
diff --git a/filters/psonly600-filter.x b/filters/psonly600-filter.x
new file mode 100644
index 0000000..2bfbba6
--- /dev/null
+++ b/filters/psonly600-filter.x
@@ -0,0 +1,3 @@
+# $Id$
+%define DPI 600
+%include <genericps.mh>
diff --git a/filters/r4081-filter.x b/filters/r4081-filter.x
new file mode 100644
index 0000000..f024f03
--- /dev/null
+++ b/filters/r4081-filter.x
@@ -0,0 +1,38 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the Ricoh 4081 laser printer
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 300
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r300 -sDEVICE=r4081 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/stdconv.xh b/filters/stdconv.xh
new file mode 100644
index 0000000..090b02e
--- /dev/null
+++ b/filters/stdconv.xh
@@ -0,0 +1,348 @@
+% $Id$
+%
+% Generic conversions for magicfilters
+%
+
+# PostScript
+%if HANDLE_PS
+ %define PS_OK
+ %define PSACT: pipe
+ %define FPSACT: fpipe
+%elif NATIVE_PS
+ %define HANDLE_PS: postscript
+ %define PS_OK
+ %define PSACT: filter
+ %define FPSACT: ffilter
+%else
+ %define HANDLE_PS: reject Cannot print PostScript on this printer.
+%endif
+%
+% The actual PostScript entries
+%
+0 %! HANDLE_PS
+0 \004%! HANDLE_PS
+
+# Adobe Portable Document Format (Acrobat)
+%if HANDLE_PDF
+ % We're set
+%elif GS_LANG_PDF && GS_DEVICE && !NATIVE_PS
+ %define HANDLE_PDF: ffilter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -dNODISPLAY \
+ -r[GS_RES] -sDEVICE=GS_DEVICE -sOutputFile=- -
+%elif GS_LANG_PDF && PS_OK
+ %if STDOUT
+ %define HANDLE_PDF: FPSACT PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -dNODISPLAY \
+ -sPSFile=STDOUT $FILE -c quit
+ %else
+ % This is bloody ugly...
+ %define HANDLE_PDF: FPSACT PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -dNODISPLAY \
+ -sPSFile=pdfout$$.ps $FILE -c quit ; \
+ cat pdfout$$.ps ; rm pdfout$$.ps
+ %endif
+%elif HAVE_PDF2PS
+ %if STDOUT
+ %define HANDLE_PDF: FPSACT PATH_PDF2PS $FILE STDOUT
+ %else
+ %define HANDLE_PDF: FPSACT PATH_PDF2PS $FILE pdfout$$.ps ; \
+ cat pdfout$$.ps ; rm pdfout$$.ps
+ %endif
+%endif
+%if HANDLE_PDF
+ %define PDF_OK
+%else
+ %define HANDLE_PDF: reject Cannot print PDF (Adobe Acrobat) files on \
+ this printer.
+%endif
+%
+% The actual PDF entry
+%
+0 %PDF HANDLE_PDF
+%
+% Check out a couple of common data types; if we can't handle them, see
+% if we can find something that can; also define _OK entries and appropriate
+% rejects.
+%
+% ASCII/Latin1 text
+%
+%if !HANDLE_TEXT && PS_OK
+ %if HAVE_NENSCRIPT
+ %define HANDLE_TEXT: pipe PATH_NENSCRIPT -B -p-
+ %define LATIN1_OK
+ %elif HAVE_A2X
+ %define HANDLE_TEXT: pipe PATH_A2X -p -dps -man
+ %define LATIN1_OK
+ %elif HAVE_A2PS
+ % Untested!
+ %define HANDLE_TEXT: pipe PATH_A2PS -p -nh -nn -f12 -b
+ %define LATIN1_OK
+ %endif
+%endif
+%if HANDLE_TEXT
+ %define ASCII_OK
+%else
+ %define HANDLE_TEXT: reject Cannot print text files on this printer.
+%endif
+%
+% HP PCL
+%
+%if HANDLE_PCL5E
+ %define PCL5E_OK
+ %define PCL_OK
+ %if !HANDLE_PCL
+ %define HANDLE_PCL: HANDLE_PCL5E
+ %endif
+%else
+ %define HANDLE_PCL5E: reject Cannot print PCL5E files on this printer.
+ %if HANDLE_PCL
+ %define PCL_OK
+ %else
+ %define HANDLE_PCL: reject Cannot print PCL files on this printer.
+ %endif
+%endif
+%
+% HP PJL
+%
+%if HANDLE_PJL
+ %define PJL_OK
+%else
+ %define HANDLE_PJL: reject Cannot print PJL files on this printer.
+%endif
+%
+% TeX DVI
+%
+%if !HANDLE_DVI
+ %if HAVE_DVIPS && PS_OK
+ %if NATIVE_PS
+ %if XDPI
+ %define HANDLE_DVI: ffilter PATH_DVIPS -X XDPI -Y YDPI -R -q -F -f
+ %else
+ %define HANDLE_DVI: ffilter PATH_DVIPS -D DPI -R -q -F -f
+ %endif
+ %else
+ %if XDPI
+ %define HANDLE_DVI: fpipe PATH_DVIPS -X XDPI -Y YDPI -R -q -f
+ %else
+ %define HANDLE_DVI: fpipe PATH_DVIPS -D DPI -R -q -f
+ %endif
+ %endif
+ %endif
+%endif
+%if HANDLE_DVI
+ %define DVI_OK 1
+%else
+ %define HANDLE_DVI: reject Cannot print DVI files on this printer.
+%endif
+%
+% troff
+%
+%if !HANDLE_TROFF
+ %if HAVE_GROG
+ %if HAVE_GROLJ4 && PCL5E_OK
+ %define HANDLE_TROFF: ffilter `PATH_GROG -Tlj4 $FILE`
+ %elif HAVE_GROPS && PS_OK
+ %define HANDLE_TROFF: FPSACT `PATH_GROG -Tps $FILE`
+ %elif HAVE_GRODVI && DVI_OK
+ %define HANDLE_TROFF: fpipe `PATH_GROG -Tdvi $FILE`
+ %elif HAVE_GROTTY && LATIN1_OK
+ %define HANDLE_TROFF: fpipe `PATH_GROG -Tlatin1 $FILE`
+ %elif HAVE_GROTTY && ASCII_OK
+ %define HANDLE_TROFF: fpipe `PATH_GROG -Tascii $FILE`
+ %endif
+ %elif HAVE_GROFF
+ %
+ % We don't have grog -- use options seemingly appropriate for man pages
+ %
+ %if HAVE_GROLJ4 && PCL5E_OK
+ %define HANDLE_TROFF: filter PATH_GROFF -Tlj4 -t -mandoc
+ %elif HAVE_GROPS && PS_OK
+ %define HANDLE_TROFF: PSACT PATH_GROFF -Tps -t -mandoc
+ %elif HAVE_GRODVI && DVI_OK
+ %define HANDLE_TROFF: pipe PATH_GROFF -Tdvi -t -mandoc
+ %elif HAVE_GROTTY && LATIN1_OK
+ %define HANDLE_TROFF: pipe PATH_GROFF -Tlatin1 -t -mandoc
+ %elif HAVE_GROTTY && ASCII_OK
+ %define HANDLE_TROFF: pipe PATH_GROFF -Tascii -t -mandoc
+ %endif
+ %endif
+%endif
+%if HANDLE_TROFF
+ %define TROFF_OK
+%else
+ %define HANDLE_TROFF: reject Cannot print troff files on this printer.
+%endif
+
+# TeX DVI
+0 \367\002 HANDLE_DVI
+
+# compress'd data
+%if ZCAT
+0 \037\235 pipe ZCAT
+%else
+0 \037\235 reject Cannot print compressed files on this printer.
+%endif
+
+# packed, gzipped, frozen and SCO LZH data
+%if GZCAT
+0 \037\036 pipe GZCAT
+0 \037\213 pipe GZCAT
+0 \037\236 pipe GZCAT
+0 \037\240 pipe GZCAT
+%else
+0 \037\036 reject Cannot print packed files on this printer.
+0 \037\213 reject Cannot print gzipped files on this printer.
+0 \037\236 reject Cannot print frozen files on this printer.
+0 \037\240 reject Cannot print SCO LZH files on this printer.
+%endif
+
+# troff documents
+0 .\?\?\040 HANDLE_TROFF
+0 .\\\" HANDLE_TROFF
+0 '\\\" HANDLE_TROFF
+0 '.\\\" HANDLE_TROFF
+0 \\\" HANDLE_TROFF
+
+# ditroff
+%if HAVE_GROPS && PS_OK
+0 "x T ps" PSACT PATH_GROPS
+%else
+0 "x T ps" reject Cannot print PostScript ditroff files.
+%endif
+%if HAVE_GRODVI && DVI_OK
+0 "x T dvi" pipe PATH_GRODVI
+%else
+0 "x T dvi" reject Cannot print DVI ditroff files.
+%endif
+%if HAVE_GROTTY && ASCII_OK
+0 "x T ascii" pipe PATH_GROTTY
+0 "x T latin1" pipe PATH_GROTTY
+%else
+0 "x T ascii" reject Cannot print ASCII ditroff files.
+0 "x T latin1" reject Cannot print Latin-1 ditroff files.
+%endif
+%if HAVE_GROLJ4 && PCL5E_OK
+0 "x T lj4" filter PATH_GROLJ4
+%else
+0 "x T lj4" reject Cannot print LaserJet 4 ditroff files.
+%endif
+
+# Portable bit-, grey- and pixmaps
+%if HANDLE_PNM
+ %define PNM_OK
+%elif HAVE_PNMTOPS && PS_OK
+ %define HANDLE_PNM: PSACT PATH_PNMTOPS -scale 1000 -dpi DPI 2>/dev/null
+ %define PNM_OK
+%else
+ %define HANDLE_PNM: reject Cannot print PBM/PGM/PPM files on \
+ this printer.
+%endif
+0 P1\n HANDLE_PNM
+0 P2\n HANDLE_PNM
+0 P3\n HANDLE_PNM
+0 P4\n HANDLE_PNM
+0 P5\n HANDLE_PNM
+0 P6\n HANDLE_PNM
+
+# HP Printer Control Language (PCL) -- assume start with reset code
+0 \033E\033 HANDLE_PCL
+
+# HP Printer Job Language (PJL)
+0 \033%-12345X HANDLE_PJL
+0 "@PJL " HANDLE_PJL
+0 @PJL\t HANDLE_PJL
+0 @PJL\r HANDLE_PJL
+0 @PJL\n HANDLE_PJL
+
+# GIF files
+%if HAVE_GIFTOPPM && PNM_OK
+0 GIF87a pipe PATH_GIFTOPPM 2>/dev/null
+0 GIF89a pipe PATH_GIFTOPPM 2>/dev/null
+%else
+0 GIF87a reject Cannot print GIF images on this printer.
+0 GIF89a reject Cannot print GIF images on this printer.
+%endif
+
+# JFIF (JPEG) files
+%if HAVE_DJPEG && PNM_OK
+0 \377\330\377\340\?\?JFIF\0 pipe PATH_DJPEG -pnm
+%else
+0 \377\330\377\340\?\?JFIF\0 reject Cannot print JPEG images \
+ on this printer.
+%endif
+
+# PNG files
+%if HAVE_PNGTOPNM && PNM_OK
+0 \211PNG\r\n\032\n pipe PATH_PNGTOPNM 2>/dev/null
+%else
+0 \211PNG\r\n\032\n reject Cannot print PNG images on this \
+ printer.
+%endif
+
+# TIFF files (the last two bytes of the "magic" is really a version number;
+# but the magic is really lame and as far as I have understood the version
+# number has never changed and never will, so we include it.)
+%if HAVE_TIFFTOPNM && PNM_OK
+0 MM\0\x2a pipe PATH_TIFFTOPNM 2>/dev/null
+0 II\x2a\0 pipe PATH_TIFFTOPNM 2>/dev/null
+%else
+0 MM\0\x2a pipe Cannot print TIFF images on this printer.
+0 II\x2a\0 pipe Cannot print TIFF images on this printer.
+%endif
+
+# BMP files (even lousier magic -- Microsoft strikes again!)
+%if HAVE_BMPTOPPM && PNM_OK
+0 BM\?\?\?\?\?\?\?\?\?\?\?\?\x0c pipe \
+ PATH_BMPTOPPM 2>/dev/null
+0 BM\?\?\?\?\?\?\?\?\?\?\?\?\x40 pipe \
+ PATH_BMPTOPPM 2>/dev/null
+0 BM\?\?\?\?\?\?\?\?\?\?\?\?\x28 pipe \
+ PATH_BMPTOPPM 2>/dev/null
+%else
+0 BM\?\?\?\?\?\?\?\?\?\?\?\?\x0c reject \
+ Cannot print BMP files on this printer.
+0 BM\?\?\?\?\?\?\?\?\?\?\?\?\x40 reject \
+ Cannot print BMP files on this printer.
+0 BM\?\?\?\?\?\?\?\?\?\?\?\?\x28 reject \
+ Cannot print BMP files on this printer.
+%endif
+
+# Sun rasterfiles
+%if HAVE_RASTTOPNM && PNM_OK
+0 \x59\xa6\x6a\x95 pipe PATH_RASTTOPNM 2>/dev/null
+%else
+0 \x59\xa6\x6a\x95 reject Cannot print Sun rasterfiles on this printer.
+%endif
+
+# SGI Imagelib (IRIS RGB) files
+%if IS_COLOR
+ %define SGITOPS_OPT: $FILE -cmyk
+%else
+ %define SGITOPS_OPT: $FILE
+%endif
+%if HAVE_SGITOPNM && PNM_OK
+0 \x1\xda pipe PATH_SGITOPNM 2>/dev/null
+0 \xda\x1 pipe PATH_SGITOPNM 2>/dev/null
+%elif HAVE_TOPS && sgi && PS_OK
+0 \x1\xda FPSACT PATH_TOPS SGITOPS_OPT
+0 \xda\x1 FPSACT PATH_TOPS SGITOPS_OPT
+%elif HAVE_SGITOPS && PS_OK
+0 \x1\xda FPSACT PATH_SGITOPS SGITOPS_OPT
+0 \xda\x1 FPSACT PATH_SGITOPS SGITOPS_OPT
+%else
+0 \x1\xda reject Cannot print SGI RGB files on this printer.
+0 \xda\x1 reject Cannot print SGI RGB files on this printer.
+%endif
+
+# FIG files; reported by Steven P. Hill <sph@uscbu.ih.att.com>
+%if HAVE_FIG2DEV && PS_OK
+0 #FIG pipe PATH_FIG2DEV -Lps -P -l dummy
+%else
+0 #FIG reject Cannot print FIG files on this printer.
+%endif
+
+%include <stdrejects.xh>
+
+%if TROFF_OK
+# optimistic troff magic
+0 . HANDLE_TROFF
+# wacko troff magic
+0 ''' HANDLE_TROFF
+%endif
diff --git a/filters/stdrejects.xh b/filters/stdrejects.xh
new file mode 100644
index 0000000..bf5e550
--- /dev/null
+++ b/filters/stdrejects.xh
@@ -0,0 +1,25 @@
+% $Id$
+#
+# Standard rejects... things we don't want to print
+#
+
+# Various archive formats
+257 ustar\0 reject Attempted to print a tar file.
+257 "ustar \0" reject Attempted to print a tar file.
+0 07070 reject Attempted to print a cpio file.
+0 PK\3\4 reject Attempted to print a zip file.
+20 \xdc\xa7\xc7\xfd reject Attempted to print a zoo file.
+
+# Binaries (Linux): reject with email message
+0 \013\1d\0 reject Attempted to print a compiled binary.
+0 \100\1d\0 reject Attempted to print a compiled binary.
+0 \007\1d\0 reject Attempted to print a compiled binary.
+0 \314\0d\0 reject Attempted to print a compiled binary.
+0 \177ELF reject Attempted to print an ELF object.
+0 \007\001\0 reject Attempted to print an object file.
+216 \021\001\0\0 reject Attempted to print a core dump file.
+0 !<arch> reject Attempted to print an archive.
+0 =<ar> reject Attempted to print an archive.
+
+# Don't confuse this one with troff!
+0 .snd reject Attempted to print Sun/NeXT audio data.
diff --git a/filters/tek4693-filter.x b/filters/tek4693-filter.x
new file mode 100644
index 0000000..18f8f8e
--- /dev/null
+++ b/filters/tek4693-filter.x
@@ -0,0 +1,39 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the Tektronix 4693
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 100
+%define IS_COLOR 1
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r100 -sDEVICE=t4693d8 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/filters/tek4696-filter.x b/filters/tek4696-filter.x
new file mode 100644
index 0000000..e533237
--- /dev/null
+++ b/filters/tek4696-filter.x
@@ -0,0 +1,39 @@
+# $Id$
+%include <filters.h>
+#
+# Magic filter setup file for the Tektronix 4695/4696
+# THIS FILE IS UNTESTED!
+#
+# This file is in the public domain.
+#
+# This file has been automatically adapted to your system.
+%ifndef HAVE_GHOSTSCRIPT
+# However, since you didn't have GhostScript installed, most entries
+# are going to be rejects.
+%endif
+#
+/*
+ * Printer resolution
+ */
+%define DPI 120
+%define IS_COLOR 1 /* At least I think it is */
+/*
+ * PostScript
+ */
+%ifdef HAVE_GHOSTSCRIPT
+%define HANDLE_PS filter PATH_GHOSTSCRIPT -q -dSAFER -dNOPAUSE -r120 -sDEVICE=t4696 -sOutputFile=- -
+%endif
+/*
+ * Text
+ */
+%define HANDLE_TEXT text
+/*
+ * Native here to override PCL magic
+ */
+# wild guess: native control codes start with <ESC>
+0 \033 cat
+
+%include <stdconv.mh>
+
+# Default entry -- for normal (text) files. MUST BE LAST.
+default HANDLE_TEXT
diff --git a/ghostprobe.c b/ghostprobe.c
new file mode 100644
index 0000000..af71dda
--- /dev/null
+++ b/ghostprobe.c
@@ -0,0 +1,112 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1996-1998 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * ghostprobe - attempt to figure out what our version of Ghostscript
+ * can do.
+ *
+ * This program would have been written in Perl, but I didn't want to make
+ * the existence of Perl a condition to build magicfilter.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "config.h"
+
+#define WHITESPACE "\b\t\n\v\f\r "
+
+#ifndef HAVE_GHOSTSCRIPT
+
+main()
+{
+ exit(0); /* No Ghostscript to probe! */
+}
+
+#else /* HAVE_GHOSTSCRIPT */
+
+main(int argc, char *argv[])
+{
+ FILE *gs;
+ char line[2048], *p;
+ enum { st_devs, st_lang, st_ignore } state;
+ static char *prefix[] = { "GS_DEV_", "GS_LANG_" };
+ int lang_info = 0;
+
+ gs = popen(PATH_GHOSTSCRIPT " -help", "r");
+ if ( !gs )
+ exit(1);
+
+ printf("/*\n"
+ " * Ghostscript configuration summary. Automatically generated\n"
+ " * by ghostprobe.\n"
+ " */\n"
+ "\n");
+
+ state = st_ignore; /* Parser state */
+
+ while ( fgets(line, 2048, gs) != NULL )
+ {
+ if ( strchr(WHITESPACE, line[0]) )
+ {
+ switch(state)
+ {
+ case st_ignore:
+ break; /* Do nothing */
+ case st_devs:
+ case st_lang:
+ p = strtok(line, WHITESPACE);
+ while ( p )
+ {
+ printf("#define %s%s 1\n", prefix[state], p);
+ p = strtok(NULL, WHITESPACE);
+ }
+ break;
+ }
+ }
+ else if ( !strcmp("Available devices:\n", line) )
+ state = st_devs;
+ else if ( !strcmp("Language interpreters:\n", line) )
+ {
+ state = st_lang;
+ lang_info = 1; /* We have a language info section */
+ }
+ else if ( !strncmp("Input formats: ", line, 15) )
+ {
+ state = st_lang;
+ lang_info = 1;
+ /* The rest of the line needs to be interpreted */
+ p = strtok(line+15, WHITESPACE);
+ while ( p )
+ {
+ printf("#define %s%s 1\n", prefix[state], p);
+ p = strtok(NULL, WHITESPACE);
+ }
+ }
+ else
+ state = st_ignore;
+ }
+
+ pclose(gs);
+
+ if ( !lang_info )
+ {
+ /* Older versions of Ghostscript lacked the Language Interpreters
+ information; just define PostScript without being specific */
+ printf("#define GS_LANG_PostScript 1\n");
+ }
+
+ exit(0);
+}
+
+#endif /* HAVE_GHOSTSCRIPT */
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..89fc9b0
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/loadconfig.c b/loadconfig.c
new file mode 100644
index 0000000..08b99cd
--- /dev/null
+++ b/loadconfig.c
@@ -0,0 +1,208 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1995-1998 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * loadconfig.c
+ *
+ * Load the configuration file
+ */
+
+#include "magicfilter.h"
+
+#define MAX_LINE 4096 /* Size of line buffer */
+
+#define die(M) do { fprintf(stderr, "%s:%d: %s\n", file, lineno, (M)); \
+ fclose(f); return NULL; } while(0);
+
+/*
+ * char *getline(FILE *f, char *file, int *lineno)
+ *
+ * Get a logical line from file f; returning a pointer to the allocated
+ * storage. Advance the line pointer by # of lines. file used for
+ * error messages.
+ */
+
+static char *getline(FILE *f, char *file, int *line)
+{
+ char *buf, *p;
+ int buflen, spc, ch, bslash;
+ int lineno = *line;
+
+ buf = p = malloc(BUFSIZ);
+ if ( !buf ) die("Out of memory");
+ buflen = spc = BUFSIZ;
+
+ bslash = 0;
+
+ while(1)
+ {
+ if ( !spc ) /* Risk for overrun? */
+ {
+ spc = p-buf;
+ if ( !(buf = realloc(buf, buflen += BUFSIZ)) )
+ die("Out of memory");
+ p = buf+spc;
+ spc = BUFSIZ;
+ }
+
+ ch = getc(f);
+
+ if ( ch == EOF )
+ {
+ if ( p == buf )
+ {
+ free(buf);
+ return NULL; /* EOF */
+ }
+ else
+ {
+ bslash = 0;
+ ch = '\n'; /* End of file -> end of line */
+ }
+ }
+
+ if ( ch == '\n' )
+ {
+ lineno++;
+
+ if ( bslash )
+ {
+ p--; /* Delete backslash-newline combo */
+ spc++;
+ while ( isspace(ch = getc(f)) ); /* Ignore leading whitespace */
+ ungetc(ch, f);
+ }
+ else
+ {
+ *p = '\0';
+ *line = lineno;
+ return buf;
+ }
+ }
+ else
+ {
+ bslash = (ch == '\\');
+ *(p++) = ch;
+ spc--;
+ }
+ }
+}
+
+
+/*
+ * struct datatype *load_config(char *file)
+ *
+ * Load the configuration file, returning the pointer to the lead node.
+ * In case of error, return NULL.
+ *
+ * The variable pointed to by in_block_size is set to the size needed
+ * for the input buffer.
+ */
+
+struct datatype *load_config(char *file, int *in_block_size)
+{
+ FILE *f;
+ struct datatype *head = NULL; /* Head pointer to linked list */
+ struct datatype **next = &head; /* Chase pointer to store in order */
+ struct datatype *new;
+ char *line, *p;
+ int lineno = 0;
+ int max_line = 0;
+ int bytes_needed = 0;
+ int offset;
+ int i;
+
+ f = fopen(file, "r");
+ if ( !f )
+ {
+ perror(file);
+ return NULL;
+ }
+
+ while ( (line = getline(f, file, &lineno)) != NULL )
+ {
+ offset = getoffset(line, &p);
+
+ if ( offset == MAG_ERR ) die("Syntax error");
+
+ if ( offset != MAG_COMMENT )
+ {
+ new = (struct datatype *) malloc(sizeof(struct datatype));
+ if ( !new ) die("Out of memory");
+
+ if ( offset == MAG_DEFAULT )
+ {
+ new->offset = new->length = 0;
+ new->magic = new->mask = "";
+ }
+ else
+ {
+ i = getmagic(p, NULL, NULL, NULL); /* Get length of magic */
+ if ( i < 0 ) die("Syntax error");
+ new->offset = offset;
+ new->length = i;
+ new->magic = malloc(i);
+ new->mask = malloc(i);
+ if ( !(new->magic && new->mask) ) die("Out of memory");
+ if ( offset+i > bytes_needed )
+ bytes_needed = offset+i;
+#if DEBUG > 3
+ fprintf(stderr,"magic bytes: %d\n", i);
+#endif
+ getmagic(p, &p, new->magic, new->mask);
+ }
+
+ if ( (new->action = getaction(p, &p)) < 0 )
+ die("Invalid action");
+
+ if ( (i = strlen(p)) > 0 )
+ {
+ if ( !(new->command = malloc(i+1)) )
+ die("Out of memory");
+ strcpy(new->command, p);
+ }
+ else
+ new->command = "";
+
+ /* Complete the linked list */
+ new->next = NULL;
+ *next = new;
+ next = &(new->next);
+
+#if DEBUG > 2
+ fprintf(stderr,"Added config entry: \n");
+ fprintf(stderr," offset = %d\n", new->offset);
+ fprintf(stderr," length = %d\n", new->length);
+ fprintf(stderr," action = %d\n", new->action);
+ fprintf(stderr," command = %s\n", new->command);
+ fprintf(stderr," bytes = ");
+
+ for ( i = 0 ; i < new->length ; i++ )
+ {
+ if ( (new->mask)[i] )
+ fprintf(stderr,"%03o ", (unsigned char)(new->magic)[i]);
+ else
+ fprintf(stderr,"??? ");
+ }
+ fprintf(stderr,"\n");
+#endif
+ }
+ free(line);
+ }
+
+ fclose(f);
+
+ if ( in_block_size ) *in_block_size = bytes_needed;
+
+ return head;
+}
diff --git a/magicfilter.c b/magicfilter.c
new file mode 100644
index 0000000..e15a35c
--- /dev/null
+++ b/magicfilter.c
@@ -0,0 +1,1240 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1993-1998 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * magicfilter.c
+ *
+ * "Magic" default filter for lpr/lpd which attempt to identify
+ * the type of file and filter it accordingly
+ *
+ */
+
+#include "magicfilter.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+char *inblock; /* Block read */
+int inblock_size; /* Bytes reserved for the inblock */
+int inblock_len; /* Number of bytes read (<= inblock_size) */
+int done = 0; /* Set to 1 if no more iterations */
+char *program; /* Set to argv[0] in main() */
+char *config_file = NULL; /* Configuration file */
+int debug_flag = 0; /* If debugging */
+
+/* What to call ourselves in case of failure */
+#define ERR_NAME (config_file ? config_file : program)
+
+extern const struct datatype dtypetab[]; /* Table of magic */
+
+/* Location of the mailer */
+#ifndef NOMAIL
+#ifndef SENDMAIL
+#ifdef _PATH_SENDMAIL
+/* Path defined in paths.h */
+#define SENDMAIL _PATH_SENDMAIL
+#else
+#ifdef HAVE_SENDMAIL
+/* Path defined by autoconf */
+#define SENDMAIL PATH_SENDMAIL
+#endif
+#endif
+#endif
+#ifndef SENDMAIL
+/* We couldn't find a mailer anywhere -- disable mail */
+#define NOMAIL 1
+#endif
+#endif
+
+/* Header of mail message */
+#ifndef NOMAIL
+const char *mailheader = /* Header of complaint message */
+"To: %s\n\
+Subject: Rejected print job\n\
+
+Your print job was automatically rejected as an invalid data type.\n\n";
+#endif
+
+/* ------------------------------------------------------------------------- *
+ * Fudging of certain functions if we do not have them. None of these
+ * are very good to use, but are better than nothing.
+ * ------------------------------------------------------------------------- */
+
+#ifndef HAVE_DUP2
+int dup2(int fd1, int fd2)
+
+#ifdef F_DUPFD
+{
+ close(fd2);
+ return fcntl(fildes, F_DUPFD, fd2);
+}
+#else
+{
+ int rtn;
+
+ close(fd2); /* Might return error if unused, is OK */
+ rtn = dup(fd1);
+
+ if ( rtn >= 0 && rtn != fd2 )
+ {
+ fprintf(stderr, "%s: dup() trick failed -- aborting\n", ERR_NAME);
+ exit(1);
+ }
+
+ return rtn;
+}
+#endif
+
+#endif
+
+/*
+ * Special implementation of tmpnam, that uses a dedicated "play"
+ * directory, which can be created atomically. This should hopefully
+ * remove the race condition/security risk associated with symlinks
+ * in /tmp.
+ */
+
+#define L_my_tmpnam (40+6*sizeof(pid_t)+2*sizeof(time_t))
+
+static char my_tmp_dir[24+3*sizeof(pid_t)+2*sizeof(time_t)];
+
+void gen_my_tmpdir(void)
+{
+ time_t now;
+ pid_t pid;
+ unsigned long count;
+ int ok = 0;
+ struct stat st;
+
+ pid = getpid();
+ time(&now);
+
+ for ( count = 0 ; count < 0xffffffff ; count++ ) {
+ sprintf(my_tmp_dir, "/tmp/mftmp.%lx.%lu.%lx",
+ (unsigned long)now, (unsigned long)pid, count);
+
+ if ( !mkdir(my_tmp_dir, 0777) ) {
+ /* Make sure we really created a directory in /tmp */
+ if ( lstat(my_tmp_dir, &st) || !S_ISDIR(st.st_mode) ||
+ st.st_uid != geteuid() || st.st_gid != getegid() ) {
+ /* Not a directory, or we're symlinked off */
+ rmdir(my_tmp_dir);
+ continue;
+ }
+ /* Success! */
+ return;
+ }
+
+ switch ( errno ) {
+ case EEXIST:
+ case EACCES:
+ break;
+
+ default:
+ fprintf(stderr, "%s: mkdir() failed", ERR_NAME);
+ perror("");
+ exit(1);
+ }
+ }
+
+ /* Could not create directory */
+
+ fprintf(stderr, "%s: Could not create temp directory\n", ERR_NAME);
+ exit(1);
+}
+
+char *my_tmpnam(char *buf)
+{
+ static char tmp_buf[L_my_tmpnam];
+ static unsigned long count = 0;
+
+ if ( !buf ) buf = tmp_buf;
+
+ /* We incorporate the PID because we may be forked, which could
+ * make "count" possibly non-unique */
+
+ sprintf(buf, "%s/%lu.%lx", my_tmp_dir,
+ (unsigned long) getpid(), count++);
+
+ return buf;
+}
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+/*
+ * "Cleanup list" -- list of file entries we should unlink() as part
+ * of final cleanup.
+ */
+
+struct cleanup {
+ struct cleanup *next;
+ char name[1];
+} *cleanup_list = NULL;
+
+void add_to_cleanup_list(char *name)
+{
+ struct cleanup *cent;
+
+ cent = (struct cleanup *)malloc(sizeof(struct cleanup) + strlen(name));
+ if ( !cent ) {
+ perror(ERR_NAME);
+ exit(1);
+ }
+
+ strcpy(cent->name, name);
+
+ cent->next = cleanup_list;
+ cleanup_list = cent;
+}
+
+/* ------------------------------------------------------------------------- *
+ * run(command)
+ *
+ * Similar to system(), but always run a specified shell and does not
+ * fork. We don't want to fork because we are creating a pipe, anyway.
+ *
+ * The shell is defined in SYSSHELL and is called as
+ * ``<SYSSHELL> -c command_line''
+ * ------------------------------------------------------------------------- */
+
+#ifndef SYSSHELL
+#ifdef _PATH_BSHELL
+#define SYSSHELL _PATH_BSHELL
+#else
+#define SYSSHELL "/bin/sh"
+#endif
+#endif
+#ifndef SHELLFLAG
+#define SHELLFLAG "-c"
+#endif
+
+void run(char *command)
+{
+ execl(SYSSHELL,SYSSHELL,SHELLFLAG,command,(char *)NULL);
+ exit(255); /* If we get here, the exec failed */
+}
+
+
+/* ------------------------------------------------------------------------- *
+ * fork_daemon()
+ *
+ * Fork a process that doesn't have to be wait'ed on. This it done by
+ * forking *twice* and orphanning the grandchild process, leaving it
+ * adopted by init. Do a reasonable job of propagating errors.
+ *
+ * Returns 0 for the child and 1 for the parent if OK; otherwise -1.
+ * (The reason the parent returns 1 is that is *doesn't know* the pid of
+ * the spawned child process.)
+ * ------------------------------------------------------------------------- */
+
+/* This is for non-POSIX compliant systems */
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 0xff) == 0)
+#endif
+
+#ifndef HAVE_WAITPID
+/* We don't have waitpid(), we have to emulate it */
+#ifdef HAVE_WAIT4
+/* With wait4() we should be set */
+#define waitpid(p,s,o) wait4(p, s, o, NULL)
+#else
+/* This is a feeble implementation using wait(); it doesn't implement
+ the full waitpid() semantics, but should be close enough for
+ what we need. Use with caution. */
+pid_t waitpid(pid_t pid, int *status, int options)
+{
+ pid_t retval;
+ do
+ retval = wait(status);
+ while ( retval > 0 && retval != pid );
+ return retval;
+}
+#endif
+#endif
+
+int fork_daemon(void)
+{
+ pid_t pid;
+ int status;
+
+ pid = fork();
+ if ( pid < 0 )
+ return -1; /* Error on first fork */
+ else if ( pid == 0 )
+ {
+ pid = fork();
+ if ( pid < 0 )
+ _exit(errno);
+ else if ( pid == 0 )
+ return 0; /* Child process */
+ else
+ _exit(0);
+ }
+ else
+ {
+ waitpid(pid,&status,0);
+ if (status) /* Did we return error? */
+ {
+ errno = WIFEXITED(status) ? WEXITSTATUS(status) : EINTR;
+ return -1;
+ }
+ return 1; /* Parent process */
+ }
+}
+
+
+/* ------------------------------------------------------------------------- *
+ * cat(from, to)
+ *
+ * Copy from one FILE * to another.
+ * ------------------------------------------------------------------------- */
+void cat(FILE *from, FILE *to)
+{
+ char cat_block[BUFSIZ];
+ int len;
+
+ if ( from == stdin && inblock_len > 0 ) {
+ fwrite(inblock,1,inblock_len,to);
+ inblock_len = 0;
+ }
+
+ while( ( len = fread(cat_block,1,BUFSIZ,from) ) > 0 ) {
+ fwrite(cat_block,1,len,to);
+ }
+}
+
+/* ------------------------------------------------------------------------- *
+ * do_cat(file)
+ * act_cat(opt_string)
+ *
+ * Feed the input to a specified file without any processing whatsoever.
+ *
+ * act_cat() is the action; it will attempt to extract a prefix and suffix
+ * string from the included option string as well.
+ * ------------------------------------------------------------------------- */
+void do_cat(FILE *f)
+{
+ cat(stdin, f);
+}
+
+typedef void datafunc(FILE *);
+void do_prefix_suffix(char *opt_str, datafunc *convfunc, FILE *f)
+{
+ char *p, *prefix, *suffix = NULL;
+ int n;
+
+ if ( (n = getmagic(opt_str,&p,NULL,NO_WILD)) >= 0 )
+ {
+ if ( n > 0 )
+ {
+ if ( !(prefix = malloc(n)) )
+ {
+ fprintf(stderr, "%s: Out of memory\n", ERR_NAME);
+ exit(1);
+ }
+ getmagic(opt_str,&p,prefix,NO_WILD);
+ fwrite(prefix,1,n,f); /* Write prefix string */
+ free(prefix);
+ }
+ if ( (n = getmagic(p,NULL,NULL,NO_WILD)) > 0 )
+ {
+ if ( !(suffix = malloc(n)) )
+ {
+ fprintf(stderr, "%s: Out of memory\n", ERR_NAME);
+ exit(1);
+ }
+ getmagic(p,NULL,suffix,NO_WILD);
+ }
+ }
+
+ convfunc(f);
+
+ if ( suffix )
+ {
+ fwrite(suffix,1,n,f);
+ free(suffix);
+ }
+}
+
+void act_cat(char *opt_str)
+{
+ if ( debug_flag )
+ fprintf(stderr, "cat %s\n", opt_str);
+
+ do_prefix_suffix(opt_str, do_cat, stdout);
+ done = 1;
+}
+
+/* ------------------------------------------------------------------------- *
+ * act_addcr()
+ *
+ * Feed the input to the output, substituting:
+ * \n -> \r\n \f -> \r\f
+ *
+ * It also adds \r\f at the end of the file.
+ *
+ * Used for printers which need CR's at line endings. Note that if your
+ * printer supports a different character set (say Roman-8) than your host
+ * (say Latin-1) you may be better off using ACT_FILTER and a translating
+ * filter such as "lpchar".
+ * ------------------------------------------------------------------------- */
+
+void addcr(FILE *f)
+{
+ char *p;
+ int i;
+
+ do
+ {
+ for ( i = inblock_len, p = inblock ; i ; i--, p++ )
+ {
+ switch ( *p )
+ {
+ case '\n':
+ case '\f':
+ putc('\r', f);
+ /* Fall through */
+
+ default:
+ putc(*p, f);
+ break;
+ }
+ }
+
+ inblock_len = fread(inblock, 1, inblock_size, stdin);
+ }
+ while ( inblock_len > 0 );
+
+ putc('\r', f);
+ putc('\f', f);
+}
+
+
+void act_addcr(char *opt_str)
+{
+ if ( debug_flag )
+ fprintf(stderr, "text %s\n", opt_str);
+
+ do_prefix_suffix(opt_str, addcr, stdout);
+ done = 1;
+}
+
+/* ------------------------------------------------------------------------- *
+ * act_ps()
+ *
+ * Like act_addcr() but add a Ctrl-D to the end (PostScript End of Job).
+ * Keeps the printer from running two jobs together. nenscript in
+ * particular is bad with this.
+ * ------------------------------------------------------------------------- */
+
+void act_ps(void)
+{
+ if ( debug_flag )
+ fprintf(stderr, "postscript\n");
+
+ addcr(stdout);
+ putchar('\4');
+ done = 1;
+}
+
+
+/* ------------------------------------------------------------------------- *
+ * act_drop()
+ *
+ * Just sets the done flag.
+ * ------------------------------------------------------------------------- */
+
+void act_drop(void)
+{
+ if ( debug_flag )
+ fprintf(stderr, "ignore\n");
+
+ done = 1;
+}
+
+
+/* ------------------------------------------------------------------------- *
+ * act_reject(message,user,host)
+ *
+ * Sends a rejection message to the user. A bad file (such as an executable
+ * binary) was encountered.
+ * ------------------------------------------------------------------------- */
+
+#ifndef NOMAIL
+void act_reject(char *message, char *user, char *host)
+{
+ int fildes[2]; /* File descriptors for pipe */
+ pid_t pid;
+ FILE *msg; /* Outgoing pipe */
+ char address[BUFSIZ]; /* Buffer to create address */
+ int status;
+
+ if ( debug_flag )
+ fprintf(stderr, "reject %s\n", message);
+
+#ifdef BANG_ADDRESS
+ sprintf(address,"%s!%s", host, user);
+#else
+ sprintf(address,"%s@%s", user, host);
+#endif
+
+ if ( pipe(fildes) )
+ {
+ perror(ERR_NAME);
+ exit(1);
+ }
+
+ pid = fork();
+
+ if ( pid < 0 ) { /* Fork failed */
+ perror(ERR_NAME);
+ exit(1);
+ } else if ( pid == 0 ) { /* Child process */
+ close(fildes[1]);
+ dup2(fildes[0],STDIN_FILENO); /* Redirect stdin */
+ execl(SENDMAIL,SENDMAIL,address,(char *) NULL);
+ exit(255); /* Exec failed */
+ } else { /* Parent process */
+ close(fildes[0]);
+ msg = fdopen(fildes[1],"wb"); /* Make pipe file pointer */
+
+ fprintf(msg, mailheader, address);
+ fprintf(msg, "%s\n", message);
+ fclose(msg);
+
+ waitpid(pid,&status,0);
+
+ if ( status ) {
+ fprintf(stderr, "%s: %s failed\n", ERR_NAME, SENDMAIL);
+ }
+ }
+
+ done = 1;
+}
+#else
+#define act_reject(MSG,USR,HST) act_drop()
+#endif
+
+
+/* ------------------------------------------------------------------------- *
+ * act_filter(command, redirect)
+ *
+ * Set up a pipe and filter the input through that command. Output goes
+ * to stdout.
+ * ------------------------------------------------------------------------- */
+
+static void filter_run_redirect(char *command, int redirect)
+{
+ char redir_name[L_my_tmpnam+5], redir_fd_name[32];
+ int redir_fd;
+ int status;
+ pid_t pid;
+
+ if ( redirect ) {
+ sprintf(redir_name, "OUT=%s", my_tmpnam(NULL));
+ if ( mkfifo(redir_name+4, 0777) ) _exit(255);
+ pid = fork();
+ if ( pid < 0 ) {
+ unlink(redir_name+4);
+ _exit(255);
+ } else if ( pid == 0 ) { /* Child process */
+ if ( (redir_fd = open(redir_name+4, O_WRONLY)) < 0 ) _exit(255);
+ sprintf(redir_fd_name, "OUTFD=%d", redir_fd);
+ putenv(redir_name);
+ putenv(redir_fd_name);
+ dup2(STDERR_FILENO,STDOUT_FILENO);
+ run(command);
+ } else { /* Parent process */
+ FILE *f = fopen(redir_name+4, "r");
+ if ( !f ) _exit(255);
+ cat(f,stdout);
+ fflush(stdout);
+ waitpid(pid,&status,0);
+ unlink(redir_name+4);
+ exit(WIFEXITED(status) ? WEXITSTATUS(status) : 255);
+ }
+ } else {
+ run(command);
+ }
+}
+
+void act_filter(char *command, int redirect)
+{
+ int fildes[2]; /* File descriptors for pipe */
+ FILE *out; /* Output file pointer */
+ pid_t pid; /* Child process ID */
+ int status;
+
+ if ( debug_flag )
+ fprintf(stderr, "%sfilter %s\n", redirect ? "r" : "", command);
+
+ if ( pipe(fildes) ) {
+ perror(ERR_NAME);
+ exit(1);
+ }
+
+ pid = fork();
+
+ if ( pid < 0 ) { /* Fork failed */
+ perror(ERR_NAME);
+ exit(1);
+ } else if ( pid == 0 ) { /* Child process */
+ close(fildes[1]);
+ dup2(fildes[0], STDIN_FILENO);
+ filter_run_redirect(command, redirect);
+ } else { /* Parent process */
+ close(fildes[0]);
+ out = fdopen(fildes[1],"w"); /* Make pipe file pointer */
+#if DEBUG > 3
+ fprintf(stderr, "filter: inblock_len == %d\n", inblock_len);
+#endif
+ cat(stdin,out); /* Send output into pipe */
+ fclose(out);
+
+ waitpid(pid,&status,0);
+
+ if ( status ) {
+ fprintf(stderr, "%s: %s failed\n", ERR_NAME, command);
+ }
+ }
+
+ done = 1;
+}
+
+/* ------------------------------------------------------------------------- *
+ * act_ffilter(command,redirect)
+ *
+ * Create a temp file; then filter the temp file through that command.
+ * Output goes to stdout.
+ * ------------------------------------------------------------------------- */
+
+void act_ffilter(char *command, int redirect)
+{
+ static char tmpbuf[L_my_tmpnam+6] = "FILE=";
+ FILE *out; /* Output file pointer */
+ int outfd; /* Output file descriptor */
+ pid_t pid; /* Child process ID */
+ int status;
+
+ if ( debug_flag )
+ fprintf(stderr, "%sffilter %s\n", redirect ? "r" : "", command);
+
+ if ( !my_tmpnam(tmpbuf+5) || !(out = fopen(tmpbuf+5, "wb")) )
+ {
+ perror(ERR_NAME);
+ exit(1);
+ }
+
+ cat(stdin,out); /* Send output to temp file */
+ fclose(out);
+
+ pid = fork();
+
+ if ( pid < 0 ) /* Fork failed */
+ {
+ perror(ERR_NAME);
+ exit(1);
+ }
+ else if ( pid == 0 ) /* Child process */
+ {
+ putenv(tmpbuf); /* Store name in $FILE */
+ outfd = open(tmpbuf+5, O_RDONLY);
+ dup2(outfd,STDIN_FILENO); /* Redirect stdin */
+ filter_run_redirect(command, redirect);
+ }
+ else /* Parent process */
+ {
+ waitpid(pid,&status,0); /* Wait for process to finish */
+
+ if ( status )
+ {
+ fprintf(stderr, "%s: %s failed\n", ERR_NAME, command);
+ }
+
+ unlink(tmpbuf+5); /* Remove temp file */
+ }
+
+ done = 1;
+}
+
+/* ------------------------------------------------------------------------- *
+ * act_pipethru(command,redirect)
+ *
+ * Pipes the output through a given command, creating a second pipe to
+ * fetch the input for re-processing.
+ * ------------------------------------------------------------------------- */
+
+void act_pipethru(char *command, int redirect)
+{
+ char redir_name[L_my_tmpnam+5], redir_fd_name[32];
+ int inpipefd[2]; /* File descriptors for input pipe */
+ int outpipefd[2]; /* File descriptors for output pipe */
+ FILE *out; /* Output file pointer */
+ pid_t pid, xpid, wpid;
+ int null; /* /dev/null */
+ int status; /* Process exit status */
+
+ if ( debug_flag )
+ fprintf(stderr, "%spipe %s\n", redirect ? "r" : "", command);
+
+ if ( pipe(inpipefd) ) {
+ die:
+ perror(ERR_NAME);
+ exit(1);
+ }
+
+ if ( redirect ) {
+ sprintf(redir_name, "OUT=%s", my_tmpnam(NULL));
+ if ( mkfifo(redir_name+4, 0777) )
+ goto die;
+ } else {
+ if ( pipe(outpipefd) )
+ goto die;
+ }
+
+ xpid = fork_daemon();
+
+ if ( xpid < 0 )
+ goto die;
+ else if ( xpid == 0 )
+ {
+ if ( redirect ) {
+ if ( (outpipefd[1] = open(redir_name+4, O_WRONLY)) < 0 )
+ _exit(255);
+ } else {
+ close(outpipefd[0]);
+ }
+
+ pid = fork();
+
+ if ( pid < 0 ) /* Fork failed */
+ goto die;
+ else if ( pid == 0 ) /* Child process */
+ {
+ close(inpipefd[1]);
+ dup2(inpipefd[0],STDIN_FILENO);
+ if ( redirect ) {
+ sprintf(redir_fd_name, "OUTFD=%d", outpipefd[1]);
+ putenv(redir_name);
+ putenv(redir_fd_name);
+ dup2(STDERR_FILENO, STDOUT_FILENO);
+ } else {
+ dup2(outpipefd[1], STDOUT_FILENO); /* Redirect stdout */
+ }
+ run(command);
+ }
+ else
+ {
+ /* Writing process */
+
+ close(inpipefd[0]);
+ close(outpipefd[1]);
+
+ out = fdopen(inpipefd[1],"wb");
+ cat(stdin,out); /* Send output into pipe */
+ fclose(out);
+
+ /* Wait for filter to exit */
+
+ if ( waitpid(pid,&status,0) < 0 )
+ perror("waitpid");
+
+ /* If status > 0 we should probably do something, but it is
+ difficult to know what we can do at this stage */
+
+ exit(0);
+ }
+ }
+ else
+ {
+ /* Reading process */
+
+ close(inpipefd[0]);
+ close(inpipefd[1]);
+
+ if ( redirect ) {
+ if ( (outpipefd[0] = open(redir_name+4, O_RDONLY)) < 0 )
+ goto die;
+
+ add_to_cleanup_list(redir_name+4);
+ } else {
+ close(outpipefd[1]);
+ }
+
+ /* Flush the stdin buffer */
+ null = open("/dev/null", O_RDONLY);
+ dup2(null, STDIN_FILENO);
+ close(null);
+ while ( fread(inblock,1,inblock_size,stdin) > 0 );
+
+ if ( dup2(outpipefd[0],STDIN_FILENO) < 0 )
+ {
+ perror("dup2");
+ exit(1);
+ } /* Redirect stdin */
+
+ close(outpipefd[0]);
+
+ rewind(stdin);
+ inblock_len = fread(inblock,1,inblock_size,stdin);
+ }
+}
+
+
+/* ------------------------------------------------------------------------- *
+ * act_fpipe(command, redirect)
+ *
+ * Creates a temp file and sends the output through a given command,
+ * creating a pipe to fetch the input for re-processing.
+ * ------------------------------------------------------------------------- */
+
+void act_fpipe(char *command, int redirect)
+{
+ char redir_name[L_my_tmpnam+5], redir_fd_name[32];
+ static char tmpbuf[L_my_tmpnam+6] = "FILE=";
+ int outpipefd[2]; /* File descriptors for output pipe */
+ FILE *out; /* Output file pointer */
+ int outfd; /* Output file descriptor */
+ pid_t pid, xpid, wpid;
+ int null; /* /dev/null */
+ int status; /* Exit status */
+
+ if ( debug_flag )
+ fprintf(stderr, "%sfpipe %s\n", redirect ? "r" : "", command);
+
+ if ( !my_tmpnam(tmpbuf+5) || !(out = fopen(tmpbuf+5,"w+b")) )
+ {
+#if DEBUG > 2
+ fprintf(stderr, "TMPBUF: %s\n", tmpbuf);
+#endif
+ die:
+ perror(ERR_NAME);
+ exit(1);
+ }
+
+ cat(stdin,out); /* Write output to file */
+ fclose(out);
+
+ if ( redirect ) {
+ sprintf(redir_name, "OUT=%s", my_tmpnam(NULL));
+ putenv(redir_name);
+ if ( mkfifo(redir_name+4, 0777) )
+ goto die;
+
+ } else {
+ if ( pipe(outpipefd) )
+ goto die;
+ }
+
+ xpid = fork_daemon();
+
+ if ( xpid < 0 )
+ {
+ perror(ERR_NAME);
+ exit(1);
+ }
+ else if ( xpid == 0 )
+ {
+ if ( redirect ) {
+ if ( (outpipefd[1] = open(redir_name+4, O_WRONLY)) < 0 )
+ _exit(255);
+ } else {
+ close(outpipefd[0]);
+ }
+
+ pid = fork();
+
+ if ( pid < 0 ) /* Fork failed */
+ {
+ perror(ERR_NAME);
+ exit(1);
+ }
+ else if ( pid == 0 ) /* Child process */
+ {
+ putenv(tmpbuf); /* Store name in $FILE */
+ outfd = open(tmpbuf+5, O_RDONLY);
+ dup2(outfd,STDIN_FILENO); /* Redirect stdin */
+ dup2(outpipefd[1],STDOUT_FILENO); /* Redirect stdout */
+ run(command);
+ }
+ else /* Parent process */
+ {
+ close(outpipefd[1]);
+
+ /* Wait for filter to finish and then remove temp file */
+
+ if ( waitpid(pid,&status,0) < 0 )
+ perror("waitpid");
+
+ /* If status > 0 we should probably do something, but it is
+ difficult to know what we can do at this stage */
+
+ unlink(tmpbuf+5);
+ exit(0);
+ }
+ }
+ else
+ {
+ /* Reading process */
+ if ( redirect ) {
+ if ( (outpipefd[0] = open(redir_name+4, O_RDONLY)) < 0 )
+ goto die;
+
+ add_to_cleanup_list(redir_name+4);
+ } else {
+ close(outpipefd[1]);
+ }
+
+ /* Flush the stdin buffer */
+ null = open("/dev/null", O_RDONLY);
+ dup2(null, STDIN_FILENO);
+ close(null);
+ while ( fread(inblock,1,inblock_size,stdin) > 0 );
+
+ if ( dup2(outpipefd[0],STDIN_FILENO) < 0 )
+ {
+ perror("dup2");
+ exit(1);
+ } /* Redirect stdin */
+
+ close(outpipefd[0]);
+
+ rewind(stdin);
+ inblock_len = fread(inblock,1,inblock_size,stdin);
+ }
+}
+
+
+/* ------------------------------------------------------------------------- *
+ * matches(block, pattern, mask, length)
+ *
+ * Returns nonzero if block matches pattern.
+ * ------------------------------------------------------------------------- */
+
+int matches(char *block, char *pattern, char *mask, int length)
+{
+ int i;
+ char *p, *q, *m;
+
+ q = block;
+ p = pattern;
+ m = mask;
+
+ for ( i = length ; i ; i-- )
+ {
+ if ( (*p ^ *q) & *m )
+ return 0;
+ q++; p++; m++;
+ }
+
+#if DEBUG > 3
+ fprintf(stderr,"Pattern: ");
+ for ( i = 0 ; i < length ; i++ )
+ {
+ fprintf(stderr,"%03o ", (unsigned char) block[i]);
+ }
+ fprintf(stderr,"\nMatches: ");
+ for ( i = 0 ; i < length ; i++ )
+ {
+ if ( mask[i] )
+ fprintf(stderr,"%03o ", (unsigned char) pattern[i]);
+ else
+ fprintf(stderr,"??? ");
+ }
+ fprintf(stderr,"\n");
+#endif
+
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- *
+ * envset(var,value)
+ *
+ * Inserts a key value into the environment
+ * ------------------------------------------------------------------------- */
+
+void envset(char *var, char *value)
+{
+ char *buf;
+
+ if ( !(buf = malloc(strlen(var)+strlen(value)+2)) )
+ {
+ fprintf(stderr, "%s: out of memory\n", ERR_NAME);
+ exit(1);
+ }
+ sprintf(buf, "%s=%s", var, value);
+ if ( putenv(buf) )
+ {
+ perror(ERR_NAME);
+ exit(1);
+ }
+ if ( debug_flag )
+ fprintf(stderr, "%s\n", buf);
+}
+
+/* ------------------------------------------------------------------------- *
+ * main(argc,argv)
+ *
+ * Analyze the input data and choose an appropriate way to handle it.
+ * ------------------------------------------------------------------------- */
+
+main(int argc, char *argv[])
+{
+ int do_cat = 0; /* True if -c option */
+ int i;
+ const struct datatype *dtab; /* Data type table */
+ const struct datatype *dt; /* Data type searched */
+ char *user = "unknown"; /* User name */
+ char *host = "unknown"; /* Host name */
+
+ program = argv[0]; /* Make available for error messages */
+
+ /* Clear these strings from environment; if we have unsetenv use it,
+ otherwise set to blank strings */
+
+#ifdef HAVE_UNSETENV
+ unsetenv("LPUSER");
+ unsetenv("LPHOST");
+ unsetenv("LPJOB");
+ unsetenv("FILE");
+ unsetenv("PRINTER");
+ unsetenv("LPFORMAT");
+ unsetenv("LPCLASS");
+ unsetenv("LPACCT");
+ unsetenv("LPCOPIES");
+ unsetenv("LPQUEUE");
+ unsetenv("ZOPT");
+ unsetenv("BANNERNAME");
+#else
+ putenv("LPUSER=");
+ putenv("LPHOST=");
+ putenv("LPJOB=");
+ putenv("FILE=");
+ putenv("PRINTER=");
+ putenv("LPFORMAT=");
+ putenv("LPCLASS=");
+ putenv("LPACCT=");
+ putenv("LPCOPIES=");
+ putenv("LPQUEUE=");
+ putenv("ZOPT=");
+ putenv("BANNERNAME=");
+#endif
+ putenv("LPINDENT=0"); /* Default to zero */
+
+ for ( i = 1 ; i < argc ; i++ ) /* Options passed by lpd */
+ {
+ if ( argv[i][0] == '-' )
+ {
+ if ( strcmp(argv[i],"-c") == 0 )
+ do_cat = 1;
+ else if ( strncmp(argv[i],"-n",2) == 0 )
+ {
+ user = (argv[i][2] || i == argc-1) ? argv[i]+2 : argv[++i];
+ envset("LPUSER", user);
+ }
+ else if ( strncmp(argv[i],"-h",2) == 0 )
+ {
+ host = (argv[i][2] || i == argc-1) ? argv[i]+2 : argv[++i];
+ envset("LPHOST", host);
+ }
+ else if ( strncmp(argv[i],"-i",2) == 0 )
+ envset("LPINDENT", argv[i]+2);
+ else if ( strncmp(argv[i],"-C",2) == 0 )
+ envset("LPCLASS", argv[i]+2);
+ else if ( strncmp(argv[i],"-F",2) == 0 )
+ envset("LPFORMAT", argv[i]+2);
+ else if ( strncmp(argv[i],"-J",2) == 0 )
+ envset("LPJOB", argv[i]+2);
+ else if ( strncmp(argv[i],"-K",2) == 0 )
+ envset("LPCOPIES", argv[i]+2);
+ else if ( strncmp(argv[i],"-L",2) == 0 )
+ envset("BANNERNAME", argv[i]+2);
+ else if ( strncmp(argv[i],"-P",2) == 0 )
+ envset("PRINTER", argv[i]+2);
+ else if ( strncmp(argv[i],"-Q",2) == 0 )
+ envset("LPQUEUE", argv[i]+2);
+ else if ( strncmp(argv[i],"-R",2) == 0 )
+ envset("LPACCT", argv[i]+2);
+ else if ( strncmp(argv[i],"-Z",2) == 0 )
+ envset("ZOPT", argv[i]+2);
+ else if ( strcmp(argv[i], "--debug") == 0 )
+ debug_flag = 1;
+ /* Ignore other options passed by lpd */
+ }
+ else if ( !config_file )
+ config_file = argv[i];
+ }
+
+ if ( !config_file ) {
+ fprintf(stderr, "%s: No configuration file specified\n", program);
+ exit(1);
+ }
+
+ umask(077); /* Protect the user's privacy */
+ gen_my_tmpdir(); /* Make play directory */
+
+ if ( do_cat ) /* Literal flag: skip config file */
+ {
+ if ( debug_flag )
+ fprintf(stderr, "(literal)\n");
+ inblock_size = BUFSIZ;
+ }
+ else
+ {
+ dtab = load_config(config_file, &i); /* Load configuration file */
+ if ( !dtab ) exit(1); /* load_config does the error message */
+ /* Round up to nearest multiple of BUFSIZ, for efficiency */
+ inblock_size = ((i+BUFSIZ-1)/BUFSIZ)*BUFSIZ;
+ }
+
+ if ( !(inblock = malloc(inblock_size)) )
+ {
+ fprintf(stderr, "%s: Out of memory\n", ERR_NAME);
+ exit(1);
+ }
+
+ inblock_len = fread(inblock,1,inblock_size,stdin);
+
+ if ( do_cat ) /* Literal flag -> always ACT_CAT */
+ {
+ cat(stdin,stdout);
+ done = 1;
+ }
+ else
+ {
+ while ( !done && inblock_len > 0 )
+ {
+ dt = dtab; /* Head of linked list */
+ while ( dt )
+ {
+ if ( dt->length < 1 ||
+ matches(inblock+dt->offset,dt->magic,dt->mask,dt->length) )
+ break;
+
+ dt = dt->next;
+ }
+
+ if ( !dt )
+ {
+ fprintf(stderr, "%s: Unknown type data and no default; \
+job sent by %s@%s)\n", ERR_NAME, user, host);
+ exit(1);
+ }
+
+ /* Now dt should point to the proper data type record to use */
+
+ switch( dt->action )
+ {
+ case ACT_CAT:
+ act_cat(dt->command);
+ break;
+
+ case ACT_DROP:
+ act_drop();
+ break;
+
+ case ACT_REJECT:
+ act_reject(dt->command, user, host);
+ break;
+
+ case ACT_FILTER:
+ act_filter(dt->command, 0);
+ break;
+
+ case ACT_RFILTER:
+ act_filter(dt->command, 1);
+ break;
+
+ case ACT_PIPE:
+ act_pipethru(dt->command, 0);
+ break;
+
+ case ACT_RPIPE:
+ act_pipethru(dt->command, 1);
+ break;
+
+ case ACT_ADDCR:
+ act_addcr(dt->command);
+ break;
+
+ case ACT_PS:
+ act_ps();
+ break;
+
+ case ACT_FFILTER:
+ act_ffilter(dt->command, 0);
+ break;
+
+ case ACT_FPIPE:
+ act_fpipe(dt->command, 0);
+ break;
+
+ case ACT_RFFILTER:
+ act_ffilter(dt->command, 1);
+ break;
+
+ case ACT_RFPIPE:
+ act_fpipe(dt->command, 1);
+ break;
+
+ default:
+ fprintf(stderr, "%s(%s): Internal error - invalid parse\n\
+Please mail your configuration file to <hpa@zytor.com>\n",
+ program, config_file);
+ return 1;
+ }
+ }
+
+#ifdef REJECT_EMPTY
+ if ( !done )
+ {
+ /* Send a message to the user informing that his/her print job
+ ended up empty */
+
+ act_reject(REJECT_EMPTY, user, host);
+ }
+#endif
+ }
+
+ /* Clean up after ourselves */
+ while ( cleanup_list ) {
+ unlink(cleanup_list->name);
+ cleanup_list = cleanup_list->next;
+ }
+ rmdir(my_tmp_dir);
+
+ return 0;
+}
diff --git a/magicfilter.h b/magicfilter.h
new file mode 100644
index 0000000..d74a654
--- /dev/null
+++ b/magicfilter.h
@@ -0,0 +1,88 @@
+/*
+ * magicfilter.h
+ *
+ * Copyright 1993-96 H. Peter Anvin
+ *
+ * Header file for the magic lpr/lpd filter
+ */
+
+#include "config.h"
+#include <stdio.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <string.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <ctype.h>
+
+/*
+ * These *must* be in the same order as the table in parseconfig.c!
+ */
+enum actions
+{
+ ACT_CAT, /* Just output the file */
+ ACT_DROP, /* Silently ignore the file */
+ ACT_REJECT, /* Mail the user and complain */
+ ACT_FILTER, /* Run through filter, then done */
+ ACT_PIPE, /* Pipe through command, then reprocess */
+ ACT_ADDCR, /* Like ACT_CAT, but \n -> \r\n, \f -> \r\f */
+ ACT_PS, /* Like ACT_ADDCR, but add PSEOJ (^D) at end */
+ ACT_FFILTER, /* Like ACT_FILTER, but use a temp file */
+ ACT_FPIPE, /* Like ACT_PIPETHRU, but use a temp file */
+ ACT_RFILTER, /* Use a different output filedescriptor */
+ ACT_RPIPE, /* d:o */
+ ACT_RFFILTER, /* d:o */
+ ACT_RFPIPE, /* d:o */
+
+ ACT_ERR = -1
+};
+
+/*
+ * Special magic actions
+ */
+
+#define MAG_ERR (-1) /* Invalid line */
+#define MAG_COMMENT (-2) /* Line is blank or comment */
+#define MAG_DEFAULT (-3) /* Action is the default action */
+#define MAG_SET (-4) /* Action is a set command */
+
+struct datatype
+{
+ struct datatype *next; /* Linked list pointer */
+ int offset; /* Where in file is ID string */
+ int length; /* Length of ID string */
+ char *magic; /* Expected ID string */
+ char *mask; /* Mask for ID string */
+ int action; /* What to do with it */
+ char *command; /* Command line, or for ACT_REJECT, */
+ /* text of complaint message */
+};
+
+/* Stuff to make stupid C compilers happy, and to fill in gaps */
+
+#ifdef NOVOID
+#define void
+#endif
+#ifdef NOCONST
+#define const
+#endif
+#ifndef DEBUG
+#define DEBUG 0
+#endif
+
+/* Function prototypes */
+
+struct datatype *load_config(char *file, int *in_block_size);
+int getoffset(char *p, char **endpos);
+int getmagic(char *p, char **endpos, char *magic, char *mask);
+enum actions getaction(char *pos, char **cmd);
+
+/* Global variables */
+
+extern int debug_flag;
+extern char NO_WILD[]; /* Used as senitel value by getmagic() */
diff --git a/magicfilter.man.in b/magicfilter.man.in
new file mode 100644
index 0000000..a76525e
--- /dev/null
+++ b/magicfilter.man.in
@@ -0,0 +1,438 @@
+.\" $Id$ -*- nroff -*-
+.TH MAGICFILTER 8 "Version 1.3" "November 1998"
+.\" man page for magicfilter
+.\" -----------------------------------------------------------------------
+.\"
+.\" Copyright 1995-1998 H. Peter Anvin - All Rights Reserved
+.\"
+.\" This file is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+.\" USA; either version 2 of the License, or (at your option) any later
+.\" version; incorporated herein by reference.
+.\"
+.\" -----------------------------------------------------------------------
+.SH NAME
+magicfilter \- automatic configurable printer filter
+.SH SYNOPSIS
+.B magicfilter
+config-file [\-\-debug] [\-c] [lpd-options]
+.SH DESCRIPTION
+.B magicfilter
+is an extensible and customizable automatic printer filter. It
+selects an appropriate conversion technique for the input data by
+seeking for
+.IR "magic numbers" ,
+and then utilizing the appropriate conversion utility.
+.PP
+.B magicfilter
+is primarily intended for use as the ``input filter'' by the
+.B lpd
+print spooler. The options accepted by
+.B magicfilter
+are exactly the ones passed to the input filter by
+.BR lpd .
+.SS OPTIONS
+Typically
+.B magicfilter
+will be invoked by
+.B lpd
+and hence provided the right options automatically. This list is
+included for reference only.
+.PP
+Note that only the
+.I \-n
+and
+.I \-h
+options may have spaces between the option letter and the option value.
+.TP
+.I \-c
+Copy the input to the output without any conversion whatsoever (used
+by
+.B lpd
+whenever the
+.I \-l
+option is passed to the
+.B lpr
+program).
+.TP
+.I "\-nuser, \-n user"
+The login name of the user who submitted the job. Available to
+subfilters as
+.BR $LPUSER .
+.TP
+.I "\-hhost, \-h host"
+The host on which the job was submitted. Available to subfilters as
+.BR $LPHOST .
+.TP
+.I "\-iindent"
+A numeric option passed by
+.BR lpd ;
+can be set by the user by the
+.I \-i
+option to
+.BR lpr.
+Although nominally used for the amount of indentation requested,
+.B magicfilter
+makes it available to subfilters for any useful purpose as
+.BR $LPINDENT .
+.TP
+.I "\-Cclassname"
+LPRng class (priority) name. Available to subfilters as
+.BR $LPCLASS .
+.TP
+.I "\-Fformat"
+Format letter (passed by LPRng only). When used as input filter (if)
+this will be
+.IR f ,
+when used as other filter types it will be the option character
+corresponding to this filter. Available to subfilters as
+.BR $LPFORMAT .
+.TP
+.I "\-Jjobname"
+The name of the printer job (passed by LPRng only). Available to
+subfilters as
+.BR $LPJOB .
+.TP
+.I "\-Kcopies"
+Copy count (passed by LPRng only). Available to subfilters as
+.BR $LPCOPIES .
+.TP
+.I "\-Lbannername"
+User name from the banner page (passed by LPRng only). Available to
+subfilters as
+.BR $BANNERNAME .
+.TP
+.I "\-Pprinter"
+Printer name (passed by LPRng only). Available to subfilters as
+.BR $PRINTER .
+.TP
+.I "\-Qqueuename"
+Spool queue name (passed by LPRng only). Available to subfilters as
+.BR $LPQUEUE .
+.TP
+.I "\-Raccountinfo"
+Accounting information (passed by LPRng only). Available to
+subfilters as
+.BR $LPACCT .
+.TP
+.I "\-Zoptions"
+LPRng ``Z-options''. The LPRng
+.B lpr
+program supports a
+.I \-Z
+option, which can be used to pass arbitrary information to the printer
+filters. Available to subfilters as
+.BR $ZOPT .
+.TP
+.I \-\-debug
+Write the name of each facility invoked (together with any options) to
+standard error. This can be useful for debugging complicated
+configuration files.
+.TP
+.I "other options"
+Any other options, such as the
+.IR \-w ,
+.IR \-l ,
+.IR \-x ,
+and
+.I \-y
+options typically passed by
+.B lpd
+are ignored.
+.SS RUNNING MAGICFILTER FROM LPD
+To run
+.B magicfilter
+from
+.B lpd
+it should be entered as one of the filters in the
+.I /etc/printcap
+file. Typically, it will be the input filter (if). Since most
+version of
+.B lpd
+do not accept arguments entered as part of the filter name, typically
+the filter name entered into the
+.I /etc/printcap
+file will simply be the name of the configuration file, which is set
+executable and starts with the line:
+.PP
+.B #! XXX_BINDIR_XXX/magicfilter
+.PP
+Most UNIX kernels will then be able to treat the configuration file
+itself as if it was the actual program.
+.PP
+This version of
+.B magicfilter
+supports the enhanced
+.B lpd
+included with the LPRng package from
+.IR dickory.sdsu.edu .
+.SS THE CONFIGURATION FILE
+The configuration file is used by
+.B magicfilter
+to redirect various types of data to the various conversion utilities.
+The configuration file is printer-specific, and often system-specific,
+depending on the available conversion programs. For example, a system
+which has GhostScript installed would be able to print PostScript to a
+non-PostScript printer, whereas other systems typically would not.
+
+The configuration file contains a sequence of lines of the form:
+.PP
+.I "offset magic facility"
+.PP
+where the
+.I offset
+represents the location of the indentification string in the data
+format,
+.I magic
+represents the identification string itself,
+.I facility
+represents the type of action to take.
+
+Blank lines and lines with a hash mark (#) as the first nonblank
+character are ignored. A line may be continued onto the next line by
+ending the line in a backslash (\e).
+
+The
+.I offset
+is a nonnegative integer, which can be represented either in decimal
+form (default), octal form (preceded by
+.IR 0 ),
+or hexadecimal form (preceded by
+.IR 0x ).
+
+The
+.I magic
+is a string of characters, which may include C-style \e-escape
+sequences. In addition, the sequence \e? can be used to represent a
+``wildcard'' byte. If the string includes spaces, the spaces have to
+be preceded by a backslash, or the entire string must be enclosed in
+double quotation marks.
+
+For ambiguous matches, the first match is used. Hence, the most
+specific match should always be placed first in the file. In
+addition, the last line may be of the form:
+.PP
+\fBdefault\fR \fIfacility\fR
+.PP
+which designates a default action to be used in case no other action
+matches. This will typically be the action for plain text.
+.SS FACILITIES
+.B magicfilter
+provides the following options for the
+.I facility
+field in the configuration file:
+.TP
+\fBcat\fR [\fIprefix\fR [\fIsuffix\fR]]
+Copy the input to the output without any conversion, like the
+.B cat
+command. If the optional
+.I prefix
+and
+.I suffix
+strings are specified, they are transmitted to the printer immediately
+before and after the data itself. The
+.I prefix
+and
+.I suffix
+strings are specified in the same way as the
+.I magic
+string (except that the wildcard sequence \e? is not permitted), and like
+the
+.I magic
+sequence can contain any control character, including nulls (\e0). To
+specify a
+.I suffix
+without a
+.IR prefix ,
+specify an empty
+.I prefix
+string enclosed in double quotes (i.e. "").
+.TP
+\fBtext\fR [\fIprefix\fR [\fIsuffix\fR]]
+Copy the input to the output, but add carriage return characters
+before every line feed and form feed character in the file, and a line
+feed-form feed sequence at end of file.
+The
+.I prefix
+and
+.I suffix
+arguments are treated the same way as for the
+.B cat
+facility; the
+.IR suffix ,
+if present, is added after the final line feed-form feed sequence.
+.TP
+\fBpostscript\fR
+Same as the
+.B text
+facility, except add an ASCII EOT (Ctrl-D) character to the end of the
+data. This lets a PostScript printer know that the end of the job has
+been reached. This is functionally equivalent to the command
+.TP
+.I " "
+\fBtext\fR "" \e004
+.TP
+\fBignore\fR
+Ignore the job; do not provide any output whatsoever.
+.TP
+\fBreject\fR \fImessage\fR
+Same as the
+.B ignore
+facility, but attempt to send an email message to the user who
+submitted the job to inform that a job has been rejected and why.
+.TP
+\fBfilter\fR \fIcommand\fR
+Run the given
+.IR command ,
+feeding it the input data, and sending the output data to the printer.
+The environment variables
+.BR LPUSER ,
+.BR LPHOST ,
+and
+.B LPINDENT
+is set to the values of the user, host and indent options passed to
+.BR magicfilter .
+Since the
+.I command
+is fed to
+.I /bin/sh
+it may contain shell special characters, and the sequences
+.BR $LPUSER ,
+.BR $LPHOST ,
+and
+.B $LPINDENT
+can be used to access the values of the passed environment variables.
+If the
+.B lpd
+daemon on the system is LPRng, the following environment variables are also
+available, see the
+.B OPTIONS
+section for details:
+.BR LPCLASS ,
+.BR LPFORMAT ,
+.BR LPJOB ,
+.BR LPCOPIES ,
+.BR BANNERNAME ,
+.BR PRINTER ,
+.BR LPQUEUE ,
+.BR LPACCT ,
+and
+.BR ZOPT .
+.TP
+\fBpipe\fR \fIcommand\fR
+Same as the
+.B filter
+facility, except that the output data is fed back into
+.B magicfilter
+for reprocessing. This is used for external filter programs which
+themselves do not produce a format that the printer can accept, but
+which can be futher processed to obtain such a format.
+.TP
+\fBffilter\fR \fIcommand\fR
+.sp -0.5
+.TP
+\fBfpipe\fR \fIcommand\fR
+Same as the
+.B filter
+and
+.B pipe
+facilities, respectively, except that the input is written to a
+temporary file before being fed to the filter program given by
+.IR command .
+This is useful for programs which require seekable input, such as
+.BR dvips ,
+or which need to do multiple passes over an input file, such as
+.BR grog .
+The environment variable
+.B FILE
+is set to the name of the temporary file (and, like the other ones, it
+can be accessed on the command line as
+.BR $FILE ).
+.TP
+\fBrfilter\fR \fIcommand\fR
+.sp -0.5
+.TP
+\fBrpipe\fR \fIcommand\fR
+.sp -0.5
+.TP
+\fBrffilter\fR \fIcommand\fR
+.sp -0.5
+.TP
+\fBrfpipe\fR \fIcommand\fR
+Same as the
+.BR filter ,
+.BR pipe ,
+.B ffilter
+and
+.B fpipe
+facilities, respectively, but the program is given a named pipe (FIFO)
+to write to rather than standard output. This is used for programs
+such as
+.BR gs (1)
+(Ghostscript), that may write diagnostic or console output on stdout.
+.sp
+The environment variable
+.B OUT
+(accessible as
+.BR $OUT )
+contains the name of this output FIFO. A file descriptor is also
+opened for writing onto this FIFO; the file descriptor number is given
+in the environment variable
+.B OUTFD
+.RB ( $OUTFD ).
+.sp
+By default, the standard output of the program is redirected to the
+.B magicfilter
+standard error.
+.SH HINTS
+Using the
+.B pipe
+facility together with
+.B zcat
+or
+.B gunzip
+lets you transparently print compressed files.
+.PP
+The
+.B netpbm
+collection of image conversion utilities contain a large number of
+very useful external filter programs.
+.PP
+Unless you have a printer capable of printing PostScript natively, you
+probably want to get a host-based PostScript interpreter, such as
+GhostScript (see
+.BR gs (1)).
+.PP
+You will probably want to examine the sample configuration files
+included with the
+.B magicfilter
+distribution before creating your own. For most systems, these
+configuration files will be usable without changes.
+.SH BUGS
+Some data formats cannot be easily identified by a simple fixed-offset
+magic number check.
+.PP
+Providing large offsets can cause
+.B magicfilter
+to take up lots of memory. Fortunately, large offsets for magic
+numbers are pretty much unheard of.
+.PP
+There is no protection against the
+.BR pipe ,
+.BR fpipe ,
+.B rpipe
+or
+.B rfpipe
+facilities going into an infinite loop.
+.PP
+.SH AUTHOR
+H. Peter Anvin <hpa@zytor.com>
+.SH SEE ALSO
+.BR printcap (5),
+.BR lpr (8),
+.BR dvips (1),
+.BR grog (1),
+.BR gs (1),
+.BR gzip (1),
+.BR troff (1).
diff --git a/mfpp.c b/mfpp.c
new file mode 100644
index 0000000..918e549
--- /dev/null
+++ b/mfpp.c
@@ -0,0 +1,1417 @@
+
+/* A Bison parser, made from mfpp.y with Bison version GNU Bison version 1.22
+ */
+
+#define YYBISON 1 /* Identify Bison output. */
+
+#define FILENAME 258
+#define ID 259
+#define TEXT 260
+#define IF 261
+#define ELIF 262
+#define ELSE 263
+#define ENDIF 264
+#define IFDEF 265
+#define IFNDEF 266
+#define INCLUDE 267
+#define CINCLUDE 268
+#define DEFINE 269
+#define UNDEF 270
+#define BOGUS 271
+
+#line 10 "mfpp.y"
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "mfpp.h"
+
+static void do_include(char *file);
+static void do_cinclude(char *file);
+static int yylex(void);
+
+
+#line 24 "mfpp.y"
+typedef union {
+ char *idsym; /* ID symbol */
+ char *file; /* file name */
+ char *deftxt; /* %define text */
+ int flag; /* truth value */
+} YYSTYPE;
+
+#ifndef YYLTYPE
+typedef
+ struct yyltype
+ {
+ int timestamp;
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ char *text;
+ }
+ yyltype;
+
+#define YYLTYPE yyltype
+#endif
+
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define YYFINAL 48
+#define YYFLAG -32768
+#define YYNTBASE 26
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 271 ? yytranslate[x] : 32)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 22,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 19, 2, 20, 2, 2, 18, 2, 24,
+ 25, 21, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 23, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 17, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = { 0,
+ 0, 3, 4, 8, 9, 12, 15, 17, 19, 22,
+ 25, 28, 31, 36, 39, 43, 46, 48, 50, 54,
+ 58, 61, 65, 67, 70, 74
+};
+
+static const short yyrhs[] = { 27,
+ 28, 0, 0, 27, 28, 22, 0, 0, 6, 29,
+ 0, 7, 29, 0, 8, 0, 9, 0, 10, 29,
+ 0, 11, 29, 0, 12, 3, 0, 13, 3, 0,
+ 14, 31, 23, 5, 0, 14, 31, 0, 14, 31,
+ 31, 0, 15, 31, 0, 31, 0, 30, 0, 29,
+ 18, 29, 0, 29, 17, 29, 0, 19, 29, 0,
+ 24, 30, 25, 0, 4, 0, 21, 31, 0, 24,
+ 31, 25, 0, 31, 20, 31, 0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+ 58, 61, 62, 65, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 77, 80, 81, 84, 85,
+ 86, 87, 90, 91, 92, 93
+};
+
+static const char * const yytname[] = { "$","error","$illegal.","FILENAME",
+"ID","TEXT","IF","ELIF","ELSE","ENDIF","IFDEF","IFNDEF","INCLUDE","CINCLUDE",
+"DEFINE","UNDEF","BOGUS","'|'","'&'","'!'","'#'","'*'","'\\n'","':'","'('","')'",
+"file","lines","line","cond","purecond","idexpr",""
+};
+#endif
+
+static const short yyr1[] = { 0,
+ 26, 27, 27, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 29, 29, 30, 30,
+ 30, 30, 31, 31, 31, 31
+};
+
+static const short yyr2[] = { 0,
+ 2, 0, 3, 0, 2, 2, 1, 1, 2, 2,
+ 2, 2, 4, 2, 3, 2, 1, 1, 3, 3,
+ 2, 3, 1, 2, 3, 3
+};
+
+static const short yydefact[] = { 2,
+ 4, 0, 0, 7, 8, 0, 0, 0, 0, 0,
+ 0, 1, 23, 0, 0, 0, 5, 18, 17, 6,
+ 9, 10, 11, 12, 0, 14, 16, 3, 21, 24,
+ 0, 18, 17, 0, 0, 0, 0, 0, 15, 22,
+ 25, 20, 19, 26, 13, 0, 0, 0
+};
+
+static const short yydefgoto[] = { 46,
+ 1, 12, 17, 18, 19
+};
+
+static const short yypact[] = {-32768,
+ 33, 14, 14,-32768,-32768, 14, 14, 9, 11, 5,
+ 5, -14,-32768, 14, 5, 14, 2,-32768, 3, 2,
+ 2, 2,-32768,-32768, 5, 1, 3,-32768,-32768,-32768,
+ 2, 12, -10, 14, 14, 5, -10, 23, 3,-32768,
+-32768, 16,-32768,-32768,-32768, 30, 36,-32768
+};
+
+static const short yypgoto[] = {-32768,
+-32768,-32768, -3, 34, -9
+};
+
+
+#define YYLAST 50
+
+
+static const short yytable[] = { 20,
+ 26, 27, 21, 22, 13, 30, 33, 28, 13, 36,
+ 29, 23, 31, 24, 41, 37, 39, 13, 34, 35,
+ 36, 15, 36, 38, 25, 15, 44, 45, 25, 47,
+ 42, 43, 14, 35, 15, 48, 40, 16, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 0, 32
+};
+
+static const short yycheck[] = { 3,
+ 10, 11, 6, 7, 4, 15, 16, 22, 4, 20,
+ 14, 3, 16, 3, 25, 25, 26, 4, 17, 18,
+ 20, 21, 20, 23, 24, 21, 36, 5, 24, 0,
+ 34, 35, 19, 18, 21, 0, 25, 24, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, -1, 16
+};
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "/usr/lib/bison.simple"
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#ifdef __cplusplus
+extern "C" {
+void *alloca (unsigned int);
+};
+#else /* not __cplusplus */
+void *alloca ();
+#endif /* not __cplusplus */
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc. */
+#endif /* not GNU C. */
+#endif /* alloca not defined. */
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYACCEPT return(0)
+#define YYABORT return(1)
+#define YYERROR goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+ transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+#define YYFAIL goto yyerrlab
+#define YYRECOVERING() (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { yychar = (token), yylval = (value); \
+ yychar1 = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { yyerror ("syntax error: cannot back up"); YYERROR; } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYPURE
+#define YYLEX yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#define YYLEX yylex(&yylval, &yylloc)
+#else
+#define YYLEX yylex(&yylval)
+#endif
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+#endif
+
+int yynerrs; /* number of parse errors so far */
+#endif /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+int yyparse (void);
+#endif
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_bcopy (from, to, count)
+ char *from;
+ char *to;
+ int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_bcopy (char *from, char *to, int count)
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 184 "/usr/lib/bison.simple"
+int
+yyparse()
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYINITDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+
+#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK (yyvsp--, yyssp--)
+#endif
+
+ int yystacksize = YYINITDEPTH;
+
+#ifdef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ int yynerrs;
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylloc;
+#endif
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ /* Give user a chance to reallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+ YYLTYPE *yyls1 = yyls;
+#endif
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+#ifdef YYLSP_NEEDED
+ /* This used to be a conditional around just the two extra args,
+ but that might be undefined if yyoverflow is a macro. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yystacksize);
+#else
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yystacksize);
+#endif
+
+ yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+ yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
+ return 2;
+ }
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+ yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
+ __yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
+ yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
+ __yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
+ __yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+ if (yyssp >= yyss + yystacksize - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+ goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+ /* Give the individual parser a way to print the precise meaning
+ of a token, for further debugging info. */
+#ifdef YYPRINT
+ YYPRINT (stderr, yychar, yylval);
+#endif
+ fprintf (stderr, ")\n");
+ }
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ if (yylen > 0)
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ int i;
+
+ fprintf (stderr, "Reducing via rule %d (line %d), ",
+ yyn, yyrline[yyn]);
+
+ /* Print the symbols being reduced, and their result. */
+ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+ fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+ fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 5:
+#line 66 "mfpp.y"
+{ do_if(yyvsp[0].flag); ;
+ break;}
+case 6:
+#line 67 "mfpp.y"
+{ do_elif(yyvsp[0].flag); ;
+ break;}
+case 7:
+#line 68 "mfpp.y"
+{ do_else(); ;
+ break;}
+case 8:
+#line 69 "mfpp.y"
+{ do_endif(); ;
+ break;}
+case 9:
+#line 70 "mfpp.y"
+{ do_if(yyvsp[0].flag); ;
+ break;}
+case 10:
+#line 71 "mfpp.y"
+{ do_if(!yyvsp[0].flag); ;
+ break;}
+case 11:
+#line 72 "mfpp.y"
+{ do_include(yyvsp[0].file); ;
+ break;}
+case 12:
+#line 73 "mfpp.y"
+{ do_cinclude(yyvsp[0].file); ;
+ break;}
+case 13:
+#line 74 "mfpp.y"
+{ do_define(yyvsp[-2].idsym,yyvsp[0].deftxt); ;
+ break;}
+case 14:
+#line 75 "mfpp.y"
+{ do_define(yyvsp[0].idsym,xstrdup("")); ;
+ break;}
+case 15:
+#line 76 "mfpp.y"
+{ do_copy(yyvsp[-1].idsym,yyvsp[0].idsym); ;
+ break;}
+case 16:
+#line 77 "mfpp.y"
+{ do_define(yyvsp[0].idsym,NULL); ;
+ break;}
+case 17:
+#line 80 "mfpp.y"
+{ yyval.flag = (id_lookup(yyvsp[0].idsym)!=NULL); ;
+ break;}
+case 18:
+#line 81 "mfpp.y"
+{ yyval.flag = yyvsp[0].flag; ;
+ break;}
+case 19:
+#line 84 "mfpp.y"
+{ yyval.flag = yyvsp[-2].flag && yyvsp[0].flag; ;
+ break;}
+case 20:
+#line 85 "mfpp.y"
+{ yyval.flag = yyvsp[-2].flag || yyvsp[0].flag; ;
+ break;}
+case 21:
+#line 86 "mfpp.y"
+{ yyval.flag = ! yyvsp[0].flag; ;
+ break;}
+case 22:
+#line 87 "mfpp.y"
+{ yyval.flag = yyvsp[-1].flag; ;
+ break;}
+case 23:
+#line 90 "mfpp.y"
+{ yyval.idsym = yyvsp[0].idsym; ;
+ break;}
+case 24:
+#line 91 "mfpp.y"
+{ yyval.idsym = xstrdup(id_lookup(yyvsp[0].idsym)->txt); ;
+ break;}
+case 25:
+#line 92 "mfpp.y"
+{ yyval.idsym = yyvsp[-1].idsym; ;
+ break;}
+case 26:
+#line 93 "mfpp.y"
+{ yyval.idsym = xstrcat(yyvsp[-2].idsym,yyvsp[0].idsym);
+ free(yyvsp[-2].idsym); free(yyvsp[0].idsym); ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 465 "/usr/lib/bison.simple"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (yyn > YYFLAG && yyn < YYLAST)
+ {
+ int size = 0;
+ char *msg;
+ int x, count;
+
+ count = 0;
+ /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ size += strlen(yytname[x]) + 15, count++;
+ msg = (char *) malloc(size + 15);
+ if (msg != 0)
+ {
+ strcpy(msg, "parse error");
+
+ if (count < 5)
+ {
+ count = 0;
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ {
+ strcat(msg, count == 0 ? ", expecting `" : " or `");
+ strcat(msg, yytname[x]);
+ strcat(msg, "'");
+ count++;
+ }
+ }
+ yyerror(msg);
+ free(msg);
+ }
+ else
+ yyerror ("parse error; also virtual memory exceeded");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror("parse error");
+ }
+
+ goto yyerrlab1;
+yyerrlab1: /* here on error raised explicitly by an action */
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+}
+#line 97 "mfpp.y"
+
+
+/*
+ * Bail out with style
+ */
+
+static int errflg = 0;
+
+void yyerror(char *msg,...)
+{
+ va_list va;
+
+ va_start(va,msg);
+ vfprintf(stderr, msg, va);
+ va_end(va);
+ putc('\n', stderr);
+ errflg = 1; /* Error occurred */
+}
+
+/*
+ * Support code for the lexer
+ */
+
+/* Character class buffer */
+static int idchar[(1 << CHAR_BIT)+1];
+static const unsigned char *idchars =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+#define is_idchar(X) (idchar[((unsigned char)(X))+1])
+
+/* Stack for %include files */
+#define MAX_INCLUDE 15
+static FILE *istack[MAX_INCLUDE+1];
+static long llmemory[MAX_INCLUDE+1];
+static int nincl;
+static FILE *infile;
+
+static void llremember(void);
+
+static void do_include(char *file)
+{
+ FILE *f;
+
+ if ( !killcount )
+ {
+ if ( nincl >= MAX_INCLUDE )
+ yyerror("Too many nested %%include files");
+ else
+ {
+ f = fopen(file, "rt");
+ if ( f )
+ {
+ istack[++nincl] = infile = f;
+ llremember(); /* Initialize file-position memory */
+ if ( debug > 1 )
+ fprintf(stderr, "%%include <%s>\n", file);
+ }
+ else
+ yyerror("Could not open %%include file %s", file);
+ }
+ }
+}
+
+/* Primitive support for cpp-style include files. We're just looking
+ for #define's, really; this is here to support autoconf-generated
+ headers. */
+
+static void do_cinclude(char *file)
+{
+ FILE *f;
+ char linebuf[8192], *id, *p;
+
+ if ( !killcount )
+ {
+ f = fopen(file, "rt");
+
+ if ( !f )
+ yyerror("Could not open %%cinclude file %s", file);
+ else
+ {
+ if ( debug > 1 )
+ fprintf(stderr, "%%cinclude <%s>\n", file);
+
+ while ( fgets(linebuf, 8192, f) )
+ {
+ if ( p = strchr(linebuf, '\n') )
+ *p = '\0';
+
+ if ( !strncmp(linebuf, "#define", 7) )
+ {
+ p = linebuf+7;
+ if ( *p != ' ' && *p != '\t' )
+ continue;
+ while ( *p == ' ' || *p == '\t' )
+ p++;
+ id = p;
+ while ( *p != ' ' && *p != '\t' && *p != '\n' && *p )
+ p++;
+ if ( *p )
+ {
+ *(p++) = '\0';
+ while ( *p == ' ' && *p == '\t' )
+ p++;
+ }
+ id_define(xstrdup(id), xstrdup(p));
+ }
+ }
+ fclose(f);
+ if ( debug > 1 )
+ fprintf(stderr, "-- End of %%cinclude --\n", file);
+ }
+ }
+}
+
+/* Character I/O */
+static int llungetc_buf[4];
+static int llungetc_ctr = 0;
+
+static int llgetc(void)
+{
+ int c;
+
+ if ( llungetc_ctr )
+ return llungetc_buf[--llungetc_ctr];
+
+ while ( (c = getc(infile)) == EOF )
+ {
+ fclose(infile);
+ if ( nincl < 1 )
+ {
+ balance_blocks();
+ break;
+ }
+ if ( debug > 1 )
+ fprintf(stderr, "-- End of %%include --\n");
+
+ infile = istack[--nincl];
+ }
+ if ( debug > 3 )
+ if ( isprint(c) )
+ fprintf(stderr, "Got: %c\n", c);
+ else
+ fprintf(stderr, "Got: %02x\n", c);
+
+ return c;
+}
+
+static void llungetc(int c)
+{
+ llungetc_buf[llungetc_ctr++] = c;
+}
+
+static void llremember(void)
+{
+ llmemory[nincl] = ftell(infile);
+}
+
+static void llreturn(void)
+{
+ llungetc_ctr = 0;
+ fseek(infile, llmemory[nincl], SEEK_SET);
+}
+
+/*
+ * Keyword to YACC token lookup - somewhat unsophisticated
+ */
+static int keyword_lookup(char *str)
+{
+ char *cand;
+ int val;
+
+#define HV(X,Y) (((X) << CHAR_BIT) + (Y))
+#define CAND(X,Y,STR,VAL) case HV(X,Y): cand = STR; val = VAL; break
+ switch ( HV(str[0], str[2]) )
+ {
+ CAND('i','\0',"if",IF);
+ CAND('i','d',"ifdef",IFDEF);
+ CAND('i','n',"ifndef",IFNDEF);
+ CAND('e','i',"elif",ELIF);
+ CAND('e','s',"else",ELSE);
+ CAND('e','d',"endif",ENDIF);
+ CAND('i','c',"include",INCLUDE);
+ CAND('c','n',"cinclude",CINCLUDE);
+ CAND('d','f',"define",DEFINE);
+ CAND('u','d',"undef",UNDEF);
+ default:
+ cand = ""; val = 0; break;
+ }
+
+ return strcmp(cand, str) ? 0 : val;
+#undef HV
+#undef CAND
+}
+
+/*
+ * The lexer itself
+ */
+
+static char tokenbuf[32768];
+static enum {
+ st_linestart, /* at the start of a line */
+ st_definetext, /* text for a %define */
+ st_expr /* an expression (body of most lines) */
+} lexstate;
+
+static void dtext(void)
+{
+ lexstate = st_definetext;
+}
+
+/*
+ * Expand a possible single macro token
+ */
+
+static void expand_macro(char *str)
+{
+ struct identifier *id;
+ char *mbuf, *p, *tbptr;
+
+ id = id_lookup(str);
+ if ( !id )
+ {
+ fputs(str, stdout);
+ }
+ else
+ {
+ tbptr = tokenbuf;
+ for ( p = id->txt ; ; )
+ {
+ if ( is_idchar(*p) )
+ *(tbptr++) = *(p++);
+ else
+ {
+ if ( tbptr > tokenbuf )
+ {
+ *tbptr = '\0';
+ expand_macro(tokenbuf);
+ tbptr = tokenbuf;
+ }
+ if ( *p )
+ putchar(*(p++));
+ else
+ break;
+ }
+ }
+ }
+}
+
+static int yylex(void)
+{
+ int c, c2; /* input character */
+ int bslash; /* backslash encounter? */
+ char *tbptr; /* token buffer pointer */
+ struct identifier *id; /* identifier lookup */
+
+ switch ( lexstate )
+ {
+ case st_linestart:
+ {
+ llremember();
+ do
+ c = llgetc();
+ while ( c == ' ' || c == '\t' );
+
+ if ( c != '%' )
+ {
+ /* Not a preprocessor command - output line */
+ llreturn();
+ tbptr = tokenbuf;
+ do
+ {
+ c = llgetc();
+ if ( !killcount )
+ {
+ if ( is_idchar(c) )
+ *(tbptr++) = c;
+ else
+ {
+ if ( tbptr > tokenbuf )
+ {
+ *tbptr = '\0';
+ expand_macro(tokenbuf);
+ tbptr = tokenbuf;
+ }
+ if ( c == EOF )
+ break;
+ putchar(c);
+ }
+ }
+ }
+ while ( c != '\n' );
+
+ return ( c == EOF ) ? 0 : c;
+ }
+ else
+ {
+ /* Must be a preprocessor command */
+
+ c = llgetc();
+ if ( !is_idchar(c) )
+ {
+ /* Preprocessor comment */
+ while ( c != '\n' && c != EOF )
+ c = llgetc();
+ return ( c == EOF ) ? 0 : c;
+ }
+
+ tbptr = tokenbuf;
+ while ( is_idchar(c) )
+ {
+ *(tbptr++) = c;
+ c = llgetc();
+ }
+ llungetc(c);
+
+ *tbptr = '\0';
+
+ c = keyword_lookup(tokenbuf);
+ if ( !c )
+ {
+ yyerror("Unknown preprocessor directive %%%s", tokenbuf);
+ c = BOGUS;
+ }
+
+ lexstate = st_expr;
+ return c;
+ }
+ }
+ case st_expr:
+ {
+ do
+ c = llgetc();
+ while ( c == ' ' || c == '\t' );
+
+ switch ( c )
+ {
+ case '<':
+ tbptr = tokenbuf;
+ while (1)
+ {
+ c = llgetc();
+ if ( c == '\n' || c == EOF )
+ {
+ yyerror("Unterminated filename in %%include");
+ return ( c == EOF ) ? 0 : c;
+ }
+ if ( c < ' ' )
+ {
+ yyerror("Bad character in filename");
+ return BOGUS;
+ }
+ if ( c == '>' )
+ break;
+ *(tbptr++) = c;
+ }
+ *tbptr = '\0';
+ yylval = xstrdup(tokenbuf);
+ /*
+ * Kluge: normally, \n wouldn't be reduced until the rule was
+ * reduced, at which point we've already switched input. Handle
+ * by reading ahead and stuffing the input buffer.
+ */
+ do
+ {
+ c = llgetc();
+ if ( c != '\n' && c != EOF && c != ' ' && c != '\t' )
+ yyerror("Junk at the end of %%include line");
+ }
+ while ( c != '\n' && c != EOF );
+ llremember();
+ llungetc(c);
+ return FILENAME;
+ case '\n':
+ lexstate = st_linestart;
+ return c;
+ case '!':
+ case '*':
+ case '(':
+ case ')':
+ return c;
+ case EOF:
+ return 0;
+ case ':':
+ lexstate = st_definetext;
+ return c;
+ case '&':
+ case '|':
+ case '#':
+ c2 = llgetc();
+ if ( c == c2 )
+ return c;
+ else
+ {
+ yyerror("Unrecognized token: %c%c", c, c2);
+ return BOGUS;
+ }
+ default:
+ if ( is_idchar(c) )
+ {
+ tbptr = tokenbuf;
+ while ( is_idchar(c) )
+ {
+ *(tbptr++) = c;
+ c = llgetc();
+ }
+ *tbptr = '\0';
+ llungetc(c);
+ yylval.idsym = xstrdup(tokenbuf);
+ return ID;
+ }
+ else
+ {
+ if ( isprint(c) )
+ yyerror("Unknown character `%c'", c);
+ else
+ yyerror("Unknown character %02x", (unsigned char)c);
+ return BOGUS;
+ }
+ }
+ }
+ case st_definetext:
+ {
+ int oldc = 0;
+
+ do
+ c = llgetc();
+ while ( c == ' ' || c == '\t' );
+
+ tbptr = tokenbuf;
+ while(1)
+ {
+ if ( (c == '\n' && oldc != '\\') || c == EOF )
+ break;
+ *(tbptr++) = c;
+ oldc = c;
+ c = llgetc();
+ }
+ *tbptr = '\0';
+ llungetc(c);
+ lexstate = st_expr;
+ yylval.deftxt = xstrdup(tokenbuf);
+ return TEXT;
+ }
+ }
+}
+
+/*
+ * This is the entry point for the lexer-parser - do initalization
+ * and call yyparse()
+ */
+
+int ppfile(FILE *f)
+{
+ unsigned const char *p;
+
+ symtab_init();
+
+ memset(idchar, 0, 1<<CHAR_BIT);
+ for ( p = idchars ; *p ; p++ )
+ idchar[*p+1] = 1;
+
+ lexstate = st_linestart;
+
+ istack[0] = infile = f;
+ nincl = 0;
+ llremember(); /* Initialize file-position memory */
+ yyparse();
+ return errflg;
+}
+
diff --git a/mfpp.h b/mfpp.h
new file mode 100644
index 0000000..55f6170
--- /dev/null
+++ b/mfpp.h
@@ -0,0 +1,68 @@
+/*
+ * mfpp.h
+ *
+ * Header file for mfpp
+ *
+ * Copyright 1996 H. Peter Anvin
+ */
+
+/* List value structure */
+struct listelm
+{
+ char *txt;
+ struct listelm *next;
+};
+
+typedef struct
+{
+ int len;
+ struct listelm *head, *tail;
+} list;
+
+/* Identifier structure */
+struct identifier
+{
+ char *name; /* name of identifier */
+ list *val; /* value of identifier */
+};
+
+/* Actions defined in mfppact.c */
+void do_if(int);
+void do_elif(int);
+void do_else(void);
+void do_endif(void);
+void balance_blocks(void);
+void do_define(char *, char *);
+void do_copy(char *, char *);
+
+/* Identifier manipulations */
+void symtab_init(void);
+void id_define(char *, list *);
+struct identifier *id_lookup(char *);
+char *id_ref(char *);
+list *id_ref_list(char *);
+
+/* List management */
+list *makelist(char *);
+list *nulllist(void);
+list *listcat(list *, list *);
+list *listapp(list *, char *);
+list *listdup(list *);
+void freelist(list *);
+
+/* Memory management - string handling */
+void *xmalloc(int);
+char *xstrdup(char *);
+char *xstrcat(char *, char *);
+
+/* Set to nonzero if we are %if-ed out */
+extern int killcount;
+
+/* Debug level */
+extern int debug;
+
+/* Error routine */
+void yyerror(char *msg, ...);
+
+/* Main routine - defined in mfpp.y */
+int ppfile(FILE *);
diff --git a/mfpp.y b/mfpp.y
new file mode 100644
index 0000000..f742c31
--- /dev/null
+++ b/mfpp.y
@@ -0,0 +1,608 @@
+/*
+ * mfpp.y
+ *
+ * magicfilter config file preprocessor
+ * Using cpp was getting very tedious...
+ *
+ * Copyright 1996 H. Peter Anvin
+ */
+
+%{
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "mfpp.h"
+
+static void do_include(char *file);
+static void do_cinclude(char *file);
+static int yylex(void);
+
+%}
+
+%union {
+ char *idsym; /* ID symbol */
+ char *file; /* file name */
+ char *txt; /* plain text */
+ struct listhdr *list; /* list of values */
+ int flag; /* truth value */
+}
+
+%token <file> FILENAME /* <filename> */
+%token <idsym> ID /* identifier */
+%token <txt> TEXT /* %define text */
+%token <txt> STRING /* quoted string */
+%token IF /* %if */
+%token ELIF /* %elif */
+%token ELSE /* %else */
+%token ENDIF /* %endif */
+%token IFDEF /* %ifdef - for similarity with cpp */
+%token IFNDEF /* %ifndef - ditto */
+%token FOR /* %for */
+%token IN /* in (keyword in %for statements) */
+%token NEXT /* %next */
+%token INCLUDE /* %include */
+%token CINCLUDE /* %cinclude */
+%token DEFINE /* %define */
+%token UNDEF /* %undef */
+%token BOGUS /* invalid token */
+
+%left '|' /* || */
+%left '&' /* && */
+%right '!' /* not */
+%left '#' /* ## */
+%right '*' /* reference */
+
+%type <flag> cond;
+%type <flag> purecond;
+%type <idsym> idexpr;
+%type <list> value;
+%type <list> values;
+
+%%
+
+file: lines line
+ ;
+
+lines: /* nothing */
+ | lines line '\n'
+ ;
+
+line: /* nothing */
+ | IF cond { do_if($2); }
+ | ELIF cond { do_elif($2); }
+ | ELSE { do_else(); }
+ | ENDIF { do_endif(); }
+ | IFDEF cond { do_if($2); }
+ | IFNDEF cond { do_if(!$2); }
+ | FOR idexpr IN values { do_for($2,$3); }
+ | NEXT { do_next(); }
+ | INCLUDE FILENAME { do_include($2); }
+ | CINCLUDE FILENAME { do_cinclude($2); }
+ | DEFINE idexpr ':' TEXT { do_define($2,$4); }
+ | DEFINE idexpr { do_define($2,xstrdup("")); }
+ | DEFINE idexpr values { do_define_list($2,$3); }
+ | UNDEF idexpr { do_define($2,NULL); }
+ ;
+
+cond: idexpr { $$ = (id_lookup($1)!=NULL); }
+ | purecond { $$ = $1; }
+ ;
+
+purecond: cond '&' cond { $$ = $1 && $3; }
+ | cond '|' cond { $$ = $1 || $3; }
+ | '!' cond { $$ = ! $2; }
+ | '(' purecond ')' { $$ = $2; }
+ ;
+
+values: value { $$ = $1; }
+ | values value { $$ = listjoin($1,$2); }
+ ;
+
+value: idexpr { $$ = id_ref_list($2,1); }
+ STRING { $$ = makelist($1); }
+ ;
+
+idexpr: ID { $$ = $1; }
+ | '*' idexpr { $$ = id_ref($2); }
+ | '(' idexpr ')' { $$ = $2; }
+ | idexpr '#' idexpr { $$ = xstrcat($1,$3);
+ free($1); free($3); }
+ ;
+
+%%
+
+/*
+ * Bail out with style
+ */
+
+static int errflg = 0;
+
+void yyerror(char *msg,...)
+{
+ va_list va;
+
+ va_start(va,msg);
+ vfprintf(stderr, msg, va);
+ va_end(va);
+ putc('\n', stderr);
+ errflg = 1; /* Error occurred */
+}
+
+/*
+ * Support code for the lexer
+ */
+
+/* Character class buffer */
+static int idchar[(1 << CHAR_BIT)+1];
+static const unsigned char *idchars =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+#define is_idchar(X) (idchar[((unsigned char)(X))+1])
+
+/* Stack for %include files */
+#define MAX_INCLUDE 15
+static FILE *istack[MAX_INCLUDE+1];
+static long llmemory[MAX_INCLUDE+1];
+static int nincl;
+static FILE *infile;
+
+static void llremember(void);
+
+static void do_include(char *file)
+{
+ FILE *f;
+
+ if ( !killcount )
+ {
+ if ( nincl >= MAX_INCLUDE )
+ yyerror("Too many nested %%include files");
+ else
+ {
+ f = fopen(file, "rt");
+ if ( f )
+ {
+ istack[++nincl] = infile = f;
+ llremember(); /* Initialize file-position memory */
+ if ( debug > 1 )
+ fprintf(stderr, "%%include <%s>\n", file);
+ }
+ else
+ yyerror("Could not open %%include file %s", file);
+ }
+ }
+}
+
+/* Primitive support for cpp-style include files. We're just looking
+ for #define's, really; this is here to support autoconf-generated
+ headers. */
+
+static void do_cinclude(char *file)
+{
+ FILE *f;
+ char linebuf[8192], *id, *p;
+
+ if ( !killcount )
+ {
+ f = fopen(file, "rt");
+
+ if ( !f )
+ yyerror("Could not open %%cinclude file %s", file);
+ else
+ {
+ if ( debug > 1 )
+ fprintf(stderr, "%%cinclude <%s>\n", file);
+
+ while ( fgets(linebuf, 8192, f) )
+ {
+ if ( p = strchr(linebuf, '\n') )
+ *p = '\0';
+
+ if ( !strncmp(linebuf, "#define", 7) )
+ {
+ p = linebuf+7;
+ if ( *p != ' ' && *p != '\t' )
+ continue;
+ while ( *p == ' ' || *p == '\t' )
+ p++;
+ id = p;
+ while ( *p != ' ' && *p != '\t' && *p != '\n' && *p )
+ p++;
+ if ( *p )
+ {
+ *(p++) = '\0';
+ while ( *p == ' ' && *p == '\t' )
+ p++;
+ }
+ id_define(xstrdup(id), xstrdup(p));
+ }
+ }
+ fclose(f);
+ if ( debug > 1 )
+ fprintf(stderr, "-- End of %%cinclude --\n", file);
+ }
+ }
+}
+
+/* Character I/O */
+static int llungetc_buf[4];
+static int llungetc_ctr = 0;
+
+static int llgetc(void)
+{
+ int c;
+
+ if ( llungetc_ctr )
+ return llungetc_buf[--llungetc_ctr];
+
+ while ( (c = getc(infile)) == EOF )
+ {
+ fclose(infile);
+ if ( nincl < 1 )
+ {
+ balance_blocks();
+ break;
+ }
+ if ( debug > 1 )
+ fprintf(stderr, "-- End of %%include --\n");
+
+ infile = istack[--nincl];
+ }
+ if ( debug > 3 )
+ if ( isprint(c) )
+ fprintf(stderr, "Got: %c\n", c);
+ else
+ fprintf(stderr, "Got: %02x\n", c);
+
+ return c;
+}
+
+static void llungetc(int c)
+{
+ llungetc_buf[llungetc_ctr++] = c;
+}
+
+static void llremember(void)
+{
+ llmemory[nincl] = ftell(infile);
+}
+
+static void llreturn(void)
+{
+ llungetc_ctr = 0;
+ fseek(infile, llmemory[nincl], SEEK_SET);
+}
+
+/*
+ * Keyword to YACC token lookup - somewhat unsophisticated
+ */
+static int keyword_lookup(char *str)
+{
+ char *cand;
+ int val;
+
+#define HV(X,Y) (((X) << CHAR_BIT) + (Y))
+#define CAND(X,Y,STR,VAL) case HV(X,Y): cand = STR; val = VAL; break
+ switch ( HV(str[0], str[2]) )
+ {
+ CAND('i','\0',"if",IF);
+ CAND('i','d',"ifdef",IFDEF);
+ CAND('i','n',"ifndef",IFNDEF);
+ CAND('e','i',"elif",ELIF);
+ CAND('e','s',"else",ELSE);
+ CAND('e','d',"endif",ENDIF);
+ CAND('i','c',"include",INCLUDE);
+ CAND('c','n',"cinclude",CINCLUDE);
+ CAND('d','f',"define",DEFINE);
+ CAND('u','d',"undef",UNDEF);
+ default:
+ cand = ""; val = 0; break;
+ }
+
+ return strcmp(cand, str) ? 0 : val;
+#undef HV
+#undef CAND
+}
+
+/*
+ * The lexer itself
+ */
+
+static char tokenbuf[32768];
+static enum {
+ st_linestart, /* at the start of a line */
+ st_definetext, /* text for a %define */
+ st_expr /* an expression (body of most lines) */
+} lexstate;
+
+static void dtext(void)
+{
+ lexstate = st_definetext;
+}
+
+/*
+ * Expand a possible single macro token
+ */
+
+static void expand_macro(char *str)
+{
+ struct identifier *id;
+ char *mbuf, *p, *tbptr;
+
+ id = id_lookup(str);
+ if ( !id )
+ {
+ fputs(str, stdout);
+ }
+ else
+ {
+ tbptr = tokenbuf;
+ for ( p = id->txt ; ; )
+ {
+ if ( is_idchar(*p) )
+ *(tbptr++) = *(p++);
+ else
+ {
+ if ( tbptr > tokenbuf )
+ {
+ *tbptr = '\0';
+ expand_macro(tokenbuf);
+ tbptr = tokenbuf;
+ }
+ if ( *p )
+ putchar(*(p++));
+ else
+ break;
+ }
+ }
+ }
+}
+
+static int yylex(void)
+{
+ int c, c2; /* input character */
+ int bslash; /* backslash encounter? */
+ char *tbptr; /* token buffer pointer */
+ struct identifier *id; /* identifier lookup */
+
+ switch ( lexstate )
+ {
+ case st_linestart:
+ {
+ llremember();
+ do
+ c = llgetc();
+ while ( c == ' ' || c == '\t' );
+
+ if ( c != '%' )
+ {
+ /* Not a preprocessor command - output line */
+ llreturn();
+ tbptr = tokenbuf;
+ do
+ {
+ c = llgetc();
+ if ( !killcount )
+ {
+ if ( is_idchar(c) )
+ *(tbptr++) = c;
+ else
+ {
+ if ( tbptr > tokenbuf )
+ {
+ *tbptr = '\0';
+ expand_macro(tokenbuf);
+ tbptr = tokenbuf;
+ }
+ if ( c == EOF )
+ break;
+ putchar(c);
+ }
+ }
+ }
+ while ( c != '\n' );
+
+ return ( c == EOF ) ? 0 : c;
+ }
+ else
+ {
+ /* Must be a preprocessor command */
+
+ c = llgetc();
+ if ( !is_idchar(c) )
+ {
+ /* Preprocessor comment */
+ while ( c != '\n' && c != EOF )
+ c = llgetc();
+ return ( c == EOF ) ? 0 : c;
+ }
+
+ tbptr = tokenbuf;
+ while ( is_idchar(c) )
+ {
+ *(tbptr++) = c;
+ c = llgetc();
+ }
+ llungetc(c);
+
+ *tbptr = '\0';
+
+ c = keyword_lookup(tokenbuf);
+ if ( !c )
+ {
+ yyerror("Unknown preprocessor directive %%%s", tokenbuf);
+ c = BOGUS;
+ }
+
+ lexstate = st_expr;
+ return c;
+ }
+ }
+ case st_expr:
+ {
+ do
+ c = llgetc();
+ while ( c == ' ' || c == '\t' );
+
+ switch ( c )
+ {
+ case '<':
+ tbptr = tokenbuf;
+ while (1)
+ {
+ c = llgetc();
+ if ( c == '\n' || c == EOF )
+ {
+ yyerror("Unterminated filename in %%include");
+ return ( c == EOF ) ? 0 : c;
+ }
+ if ( c < ' ' )
+ {
+ yyerror("Bad character in filename");
+ return BOGUS;
+ }
+ if ( c == '>' )
+ break;
+ *(tbptr++) = c;
+ }
+ *tbptr = '\0';
+ yylval = xstrdup(tokenbuf);
+ /*
+ * Kluge: normally, \n wouldn't be reduced until the rule was
+ * reduced, at which point we've already switched input. Handle
+ * by reading ahead and stuffing the input buffer.
+ */
+ do
+ {
+ c = llgetc();
+ if ( c != '\n' && c != EOF && c != ' ' && c != '\t' )
+ yyerror("Junk at the end of %%include line");
+ }
+ while ( c != '\n' && c != EOF );
+ llremember();
+ llungetc(c);
+ return FILENAME;
+
+ case '\"':
+ tbptr = tokenbuf;
+ while(1)
+ {
+ c = llgetc();
+ if ( c == '\"' )
+ {
+ c = llgetc();
+ if ( c != '\"' )
+ {
+ llungetc(c);
+ break;
+ }
+ }
+ *(tbptr++) = c;
+ }
+ *tbptr = '\0';
+ yylval.txt = xstrdup(tokenbuf);
+ return STRING;
+
+ case '\n':
+ lexstate = st_linestart;
+ return c;
+
+ case '!':
+ case '*':
+ case '(':
+ case ')':
+ return c;
+
+ case EOF:
+ return 0;
+
+ case ':':
+ lexstate = st_definetext;
+ return c;
+
+ case '&':
+ case '|':
+ case '#':
+ c2 = llgetc();
+ if ( c == c2 )
+ return c;
+ else
+ {
+ yyerror("Unrecognized token: %c%c", c, c2);
+ return BOGUS;
+ }
+
+ default:
+ if ( is_idchar(c) )
+ {
+ tbptr = tokenbuf;
+ while ( is_idchar(c) )
+ {
+ *(tbptr++) = c;
+ c = llgetc();
+ }
+ *tbptr = '\0';
+ llungetc(c);
+ yylval.idsym = xstrdup(tokenbuf);
+ return ID;
+ }
+ else
+ {
+ if ( isprint(c) )
+ yyerror("Unknown character `%c'", c);
+ else
+ yyerror("Unknown character %02x", (unsigned char)c);
+ return BOGUS;
+ }
+ }
+ }
+ case st_definetext:
+ {
+ int oldc = 0;
+
+ do
+ c = llgetc();
+ while ( c == ' ' || c == '\t' );
+
+ tbptr = tokenbuf;
+ while(1)
+ {
+ if ( (c == '\n' && oldc != '\\') || c == EOF )
+ break;
+ *(tbptr++) = c;
+ oldc = c;
+ c = llgetc();
+ }
+ *tbptr = '\0';
+ llungetc(c);
+ lexstate = st_expr;
+ yylval.txt = xstrdup(tokenbuf);
+ return TEXT;
+ }
+ }
+}
+
+/*
+ * This is the entry point for the lexer-parser - do initalization
+ * and call yyparse()
+ */
+
+int ppfile(FILE *f)
+{
+ unsigned const char *p;
+
+ symtab_init();
+
+ memset(idchar, 0, 1<<CHAR_BIT);
+ for ( p = idchars ; *p ; p++ )
+ idchar[*p+1] = 1;
+
+ lexstate = st_linestart;
+
+ istack[0] = infile = f;
+ nincl = 0;
+ llremember(); /* Initialize file-position memory */
+ yyparse();
+ return errflg;
+}
+
diff --git a/mfppact.c b/mfppact.c
new file mode 100644
index 0000000..7b13f6d
--- /dev/null
+++ b/mfppact.c
@@ -0,0 +1,276 @@
+/*
+ * mffppact.c
+ *
+ * Actions for mffpp
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "mfpp.h"
+
+/*
+ * Some simple string-memory-management
+ */
+void *xmalloc(int size)
+{
+ void *p;
+ p = (void *) malloc(size);
+ if ( !p )
+ {
+ fprintf(stderr, "Fatal error: out of memory");
+ exit(1);
+ }
+ return p;
+}
+
+char *xstrdup(char *str)
+{
+ int n;
+ char *dst;
+ n = strlen(str)+1;
+ dst = xmalloc(n);
+ memcpy(dst, str, n);
+ return dst;
+}
+
+char *xstrcat(char *s1, char *s2)
+{
+ int n1, n2;
+ char *dst;
+ n1 = strlen(s1);
+ n2 = strlen(s2)+1;
+ dst = xmalloc(n1+n2);
+ memcpy(dst, s1, n1);
+ memcpy(dst+n1, s2, n2);
+ return dst;
+}
+
+/*
+ * Handle %if et al
+ */
+
+typedef enum
+{
+ bt_if, /* In if or elif clause */
+ bt_else /* In else clause */
+} blocktype;
+
+#define MAXDEPTH 32
+
+typedef struct
+{
+ blocktype bt;
+ int is_true;
+ int was_true;
+}
+stackelm;
+
+static stackelm stack[MAXDEPTH]; /* Stack */
+static stackelm *curr; /* Current block */
+static int depth = 0;
+
+int killcount = 0; /* Count of false %if's */
+
+/* %if */
+void do_if(int cond)
+{
+ if ( depth >= MAXDEPTH )
+ {
+ yyerror("Too many nested %ifs");
+ return;
+ }
+
+ curr = &(stack[depth++]);
+ curr->bt = bt_if;
+ curr->is_true = curr->was_true = cond;
+
+ if ( !cond )
+ killcount++;
+}
+
+/* %elif */
+void do_elif(int cond)
+{
+ if ( !depth || curr->bt != bt_if )
+ {
+ yyerror("%%elif without %%if");
+ return;
+ }
+
+ if ( !curr->was_true && cond )
+ {
+ curr->is_true = curr->was_true = 1;
+ killcount--;
+ }
+ else if ( curr->is_true )
+ {
+ curr->is_true = 0;
+ killcount++;
+ }
+}
+
+/* %else */
+void do_else(void)
+{
+ if ( !depth || curr->bt != bt_if )
+ {
+ yyerror("%%else without %%if");
+ return;
+ }
+
+ if ( curr->is_true )
+ {
+ curr->is_true = 0;
+ killcount++;
+ }
+ else if ( !curr->was_true )
+ {
+ curr->is_true = 1;
+ killcount--;
+ }
+}
+
+/* %endif */
+void do_endif(void)
+{
+ if ( !depth || (curr->bt != bt_if && curr->bt != bt_else) )
+ {
+ yyerror("%%endif without %%if");
+ return;
+ }
+
+ if ( !curr->is_true )
+ killcount--;
+
+ depth--;
+ curr--;
+}
+
+/* balance_blocks - called on end of file: balance loops and conditionals */
+void balance_blocks()
+{
+ if ( depth )
+ yyerror("Unterminated %s", (curr->bt == bt_else) ? "%else":"%if");
+ killcount = 0;
+}
+
+/*
+ * Symbol table management
+ */
+
+struct symtabent
+{
+ struct identifier id;
+ struct symtabent *next;
+};
+
+#define SYMTABSIZE 733 /* Shouldn't be fixed, but this is a
+ special-purpose program */
+
+static struct symtabent *symtab[SYMTABSIZE];
+
+static int symtab_hash_func(char *str)
+{
+ unsigned int x;
+ for ( x = 0 ; *str ; *str++ )
+ {
+ x = x * 65599 + *str;
+ }
+ return x % SYMTABSIZE;
+}
+
+void symtab_init(void)
+{
+ int i;
+ for ( i = 0 ; i < SYMTABSIZE ; i++ )
+ symtab[i] = NULL;
+}
+
+/*
+ * Look up identifiers
+ */
+
+struct identifier *id_lookup(char *name)
+{
+ struct symtabent *sp;
+
+ sp = symtab[symtab_hash_func(name)];
+
+ while ( sp && strcmp(name, sp->id.name) != 0 )
+ sp = sp->next;
+
+ return &(sp->id);
+}
+
+/*
+ * Define or undefine indentifiers.
+ */
+void id_define(char *name, list *val)
+{
+ struct symtabent *sp, **stp;
+ int n;
+
+ stp = &symtab[n = symtab_hash_func(name)];
+ sp = *stp;
+
+#if 0
+ if (debug > 1)
+ if (txt)
+ fprintf(stderr, "%%define %s (%d): %s\n", name, n, txt);
+ else
+ fprintf(stderr, "%%undef %s (%d)\n", name, n);
+#endif
+
+ while ( sp && strcmp(name, sp->id.name) != 0 )
+ {
+ stp = &(sp->next);
+ sp = *stp;
+ }
+
+ if ( !sp && val )
+ {
+ sp = xmalloc(sizeof(struct symtabent));
+ sp->id.name = name;
+ sp->id.val = val;
+ sp->next = *stp;
+ *stp = sp;
+ }
+ else if ( /* sp && */ val )
+ {
+ freelist(sp->id.val);
+ sp->id.val = val;
+ free(name);
+ }
+ else if ( /* !val && */ sp )
+ {
+ *stp = sp->next;
+ free(sp->id.name);
+ freelist(sp->id.val);
+ free(sp);
+ free(name);
+ }
+ else /* !val && !sp */
+ free(name);
+}
+
+/*
+ * Functions to be called from within yacc code.
+ *
+ * do_define: Defines a single-item variable, or undef
+ * do_define_list: Defines a list variable
+ */
+
+void do_define(char *name, char *txt)
+{
+ if ( !killcount )
+ id_define(name, txt ? makelist(txt) : NULL);
+}
+
+void do_define_list(char *name, list *val)
+{
+ if ( !killcount )
+ id_define(name,val);
+}
+
diff --git a/mfpplist.c b/mfpplist.c
new file mode 100644
index 0000000..5f36c34
--- /dev/null
+++ b/mfpplist.c
@@ -0,0 +1,115 @@
+/*
+ * mfpplist.c
+ *
+ * List operations for mfpp
+ */
+
+#include <stdlib.h>
+#include "mfpp.h"
+
+/*
+ * makelist: Converts a single item into a list
+ */
+
+list *makelist(char *txt)
+{
+ list *hdr;
+
+ if ( !val )
+ return nulllist();
+
+ hdr = xmalloc(sizeof(list));
+ hdr->len = 1;
+ hdr->head = hdr->tail = xmalloc(sizeof(struct listelm));
+ hdr->head->txt = txt;
+ hdr->head->next = NULL;
+
+ return hdr;
+}
+
+/*
+ * nulllist: Make an empty list
+ */
+list *nulllist(void)
+{
+ list *hdr;
+
+ hdr = xmalloc(sizeof(list));
+ hdr->len = 0;
+ hdr->head = hdr->tail = NULL;
+ return hdr;
+}
+
+/*
+ * listcat: Concatenate two lists (freeing the old lists!)
+ */
+list *listcat(list *dst, list *src)
+{
+ dst->len += src->len;
+
+ if ( dst->tail )
+ {
+ dst->tail->next = src->head;
+ if ( src->tail )
+ dst->tail = src->tail;
+ }
+ else
+ {
+ dst->head = src->head;
+ dst->tail = src->tail;
+ }
+
+ free(src);
+
+ return dst;
+}
+
+/*
+ * listdup: Duplicate a list
+ */
+list *listdup(list *src)
+{
+ list *dst;
+ struct listelm *sp, *dp, **dpp;
+
+ dst = xmalloc(sizeof(list));
+ dst->len = src->len;
+ if ( !src->head )
+ {
+ dst->head = dst->tail = NULL;
+ }
+ else
+ {
+ dpp = &(dst->head);
+
+ for ( sp = src->head ; sp ; sp = sp->next )
+ {
+ dp = xmalloc(sizeof(struct listelm));
+ *dpp = dp;
+ dp->txt = xstrdup(sp->txt);
+ dpp = &(dp->next);
+ }
+ *dpp = NULL;
+ dst->tail = dp;
+ }
+
+ return dst;
+}
+
+/*
+ * freelist: Free the entire contents of a list
+ */
+void freelist(list *junk)
+{
+ struct listelm *p1, *p2;
+
+ p1 = junk->head;
+ while ( p1 )
+ {
+ p2 = p1;
+ p1 = p1->next;
+ free(p2);
+ }
+
+ free(junk);
+}
diff --git a/mfppmain.c b/mfppmain.c
new file mode 100644
index 0000000..3011aee
--- /dev/null
+++ b/mfppmain.c
@@ -0,0 +1,41 @@
+/*
+ * mfppmain.c
+ *
+ * Main program for mfpp
+ *
+ * Copyright 1996 H. Peter Anvin
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "mfpp.h"
+
+/*
+ * Debug level
+ */
+
+int debug = 0;
+
+int main(int argc, char *argv[])
+{
+ FILE *f;
+
+ if ( argc < 2 || argc > 3 )
+ {
+ fprintf(stderr, "Usage: %s filename [debuglevel]\n", argv[0]);
+ exit(1);
+ }
+
+ f = fopen(argv[1], "rt");
+ if ( !f )
+ {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ if ( argc == 3 )
+ debug = atoi(argv[2]);
+
+ exit(ppfile(f));
+}
diff --git a/parseconfig.c b/parseconfig.c
new file mode 100644
index 0000000..3a763bc
--- /dev/null
+++ b/parseconfig.c
@@ -0,0 +1,445 @@
+#ident "$Id$"
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 1995-1998 H. Peter Anvin - All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ * USA; either version 2 of the License, or (at your option) any later
+ * version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * parseconfig.c
+ *
+ * Routine library for parsing the configuration file
+ *
+ */
+
+#include "magicfilter.h"
+
+/*
+ * int getoffset(char *startpos, char **endpos)
+ *
+ * Returns the parsing offset (a decimal, octal or hex number, or "default").
+ * Returns the number, or one of the negative numbers
+ * MAG_DEFAULT ... is default
+ * MAG_COMMENT ... comment line
+ * MAG_ERR ... invalid offset
+ *
+ * *endpos is set to the first character after the offset, unless NULL
+ */
+
+int getoffset(char *p, char **endpos)
+{
+ int offset = 0; /* So far */
+ enum { st_start, st_zero, st_oct, st_dec, st_hex, st_done } state = st_start;
+
+#if DEBUG > 3
+ fprintf(stderr,"getoffset %s\n", p);
+#endif
+
+ while ( isspace(*p) ) p++; /* Skip leading whitespace */
+
+ while ( state != st_done )
+ {
+ switch( state )
+ {
+ case st_start:
+ switch ( *p )
+ {
+ case '\b': /* Whitespace */
+ case '\t':
+ case '\n':
+ case '\v':
+ case '\f':
+ case '\r':
+ case ' ':
+ p++;
+ break;
+
+ case '#':
+ case '\0': /* Blank line counts as comment */
+ offset = MAG_COMMENT;
+ state = st_done;
+ break;
+
+ case '0':
+ state = st_zero;
+ p++;
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ offset = *p - '0';
+ state = st_dec;
+ p++;
+ break;
+
+ case 'd':
+ if ( strncmp(p, "default", 7) )
+ {
+ offset = MAG_ERR;
+ }
+ else
+ {
+ p += 7;
+ offset = MAG_DEFAULT;
+ }
+ state = st_done;
+ break;
+
+ default:
+ offset = MAG_ERR;
+ state = st_done;
+ break;
+ }
+ break;
+
+ case st_zero:
+ if ( *p == 'x' || *p == 'X' )
+ {
+ state = st_hex;
+ p++;
+ break;
+ }
+ /* else fall through */
+
+ case st_oct:
+ if ( *p < '0' || *p > '7' )
+ {
+ state = st_done;
+ }
+ else
+ {
+ offset <<= 3;
+ offset += *(p++) - '0';
+ }
+ break;
+
+ case st_dec:
+ if ( *p < '0' || *p > '9' )
+ {
+ state = st_done;
+ }
+ else
+ {
+ offset *= 10;
+ offset += *(p++) - '0';
+ }
+ break;
+
+ case st_hex:
+ if ( *p >= '0' && *p <= '9' )
+ {
+ offset <<= 4;
+ offset += *(p++) - '0';
+ }
+ else if ( *p >= 'A' && *p <= 'F' )
+ {
+ offset <<= 4;
+ offset += *(p++) - 'A' + 10;
+ }
+ else if ( *p >= 'a' && *p <= 'f' )
+ {
+ offset <<= 4;
+ offset += *(p++) - 'a' + 10;
+ }
+ else
+ {
+ state = st_done;
+ }
+ }
+ }
+
+ if ( endpos )
+ *endpos = p; /* Where did we end? */
+
+ return offset;
+}
+
+/*
+ * int getmagic(char *startpos, char **endpos, char *magic, char *mask)
+ *
+ * Parse a magic string, returning the number of bytes in the magic string.
+ * Stores the endpoint in *endpos if requested. If magic and/or mask
+ * is NULL, do not store; used to count the number of characters in the
+ * magic/mask string.
+ *
+ * Each character in mask is either 0 for \? (don't care) or (char)-1 for
+ * any other (do care).
+ *
+ * If mask is set to the senitel value NO_WILD (a unique pointer value
+ * pointing to a bogus static string) the \? will not be interpreted
+ * as don't care; just as a regular escaped questionmark.
+ *
+ */
+char NO_WILD[1] = ""; /* Used as senitel value */
+
+int getmagic(char *p, char **endpos, char *magic, char *mask)
+{
+ int count = 0; /* Count of bytes */
+ int quote = 0; /* Quoted? */
+ int ch;
+ int wildcards = 1; /* Wildcards allowed by default */
+ enum { st_def, st_backsl, st_oct, st_hex, st_done } state = st_def;
+
+#if DEBUG > 3
+ fprintf(stderr,"getmagic %s\n", p);
+#endif
+
+ if ( mask == NO_WILD ) /* If wildcards forbidden */
+ {
+ mask = NULL; /* Don't store a mask */
+ wildcards = 0; /* Don't accept wildcards */
+ }
+
+ while ( isspace(*p) ) p++; /* Skip leading whitespace */
+
+ while ( state != st_done )
+ {
+ switch ( state )
+ {
+ case st_def:
+ switch ( *p )
+ {
+ case '\n': /* Unconditional whitespace */
+ case '\r':
+ case '\f':
+ case '\0':
+ if ( quote )
+ count = MAG_ERR;
+ state = st_done;
+ break;
+
+ case '\\': /* Backslash */
+ p++;
+ state = st_backsl;
+ break;
+
+ case '\"': /* Quote */
+ p++;
+ quote = !quote;
+ break;
+
+ case '\b': /* Whitespace */
+ case '\t':
+ case '\v':
+ case ' ':
+ if ( !quote )
+ {
+ state = st_done;
+ break;
+ }
+ /* else fall though */
+
+ default:
+ if ( magic ) *(magic++) = *p;
+ if ( mask ) *(mask++) = (char)(-1);
+ p++; count++;
+ break;
+ }
+ break;
+
+ case st_backsl: /* After backslash */
+ ch = -1;
+ switch ( *p )
+ {
+ case 'a':
+ ch = 7; /* Bell */
+ break;
+ case 'b':
+ ch = '\b'; /* Backspace */
+ break;
+ case 'e':
+ ch = 27; /* Escape */
+ break;
+ case 'f':
+ ch = '\f'; /* Form feed */
+ break;
+ case 'n':
+ ch = '\n'; /* Newline */
+ break;
+ case 'r':
+ ch = '\r'; /* Return */
+ break;
+ case 't':
+ ch = '\t'; /* Tab */
+ break;
+ case 'v':
+ ch = '\v'; /* Vtab */
+ break;
+ case 'x':
+ case 'X':
+ state = st_hex; /* Hex prefix */
+ ch = 0;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ state = st_oct; /* Octal prefix */
+ ch = *p - '0';
+ break;
+ case '?':
+ if ( wildcards )
+ {
+ if ( magic ) *(magic++) = (char)0; /* Ignore byte */
+ if ( mask ) *(mask++) = (char)0;
+ count++;
+ state = st_def;
+ break;
+ }
+ /* else fall through */
+ default:
+ ch = *p; /* Preserve character (e.g. " or \) */
+ break;
+ }
+
+ p++;
+
+ if ( state == st_backsl )
+ {
+ if ( magic ) *(magic++) = ch;
+ if ( mask ) *(mask++) = (char)(-1);
+ count++;
+ state = st_def;
+ }
+ break;
+
+ case st_oct:
+ if ( *p >= '0' && *p <='7' )
+ {
+ ch <<= 3;
+ ch += *(p++) - '0';
+ }
+ else
+ {
+ if ( magic ) *(magic++) = ch;
+ if ( mask ) *(mask++) = (char)(-1);
+ count++;
+ state = st_def; /* Do not advance p */
+ }
+ break;
+
+ case st_hex:
+ if ( *p >= '0' && *p <= '9' )
+ {
+ ch <<= 4;
+ ch += *(p++) - '0';
+ }
+ else if ( *p >= 'A' && *p <= 'F' )
+ {
+ ch <<= 4;
+ ch += *(p++) - 'A' + 10;
+ }
+ else if ( *p >= 'a' && *p <= 'f' )
+ {
+ ch <<= 4;
+ ch += *(p++) - 'a' + 10;
+ }
+ else
+ {
+ if ( magic ) *(magic++) = ch;
+ if ( mask ) *(mask++) = (char)(-1);
+ count++;
+ state = st_def; /* Do not advance p */
+ }
+ break;
+ }
+ }
+
+ if (endpos) *endpos = p;
+ return count;
+}
+
+/*
+ * enum actions getaction(char *pos, char **cmd)
+ *
+ * Reads the action proposed and returns:
+ *
+ * ACT_CAT ... output file raw
+ * ACT_DROP ... silently ignore
+ * ACT_REJECT ... mail user and complain
+ * ACT_FILTER ... run through once, then done
+ * ACT_PIPE ... run through command, then feed back through filter
+ * ACT_ADDCR ... \n -> \r\n, \f -> \r\f
+ * ACT_PS ... same as ADDCR, but add Ctrl-D at end
+ * ACT_FFILTER ... same as FILTER, but use a temp file
+ * ACT_FPIPE ... same as PIPE, but use a temp file
+ * ACT_RFILTER ... same as FILTER, but redirect to a different filedes
+ * ACT_RPIPE ... same as PIPE, but redirect to a different filedes
+ * ACT_RFFILTER ... R+F+FILTER
+ * ACT_RFPIPE ... R+F+PIPE
+ *
+ * If the command takes an argument, point cmd to it if non-NULL
+ *
+ * IMPORTANT: The matching algorithm is a bit simplistic. If any action
+ * is a proper prefix of any other action, the longer action must be first
+ * in the list.
+ */
+
+enum actions getaction(char *pos, char **cmd)
+{
+ enum actions act;
+ static char *act_strs[] = { "cat", "ignore", "reject", "filter",
+ "pipe", "text", "postscript",
+ "ffilter", "fpipe", "rfilter", "rpipe",
+ "rffilter", "rfpipe", NULL };
+ char **act_str;
+ int i;
+
+#if DEBUG > 3
+ fprintf(stderr,"getaction %s\n", pos);
+#endif
+
+ while ( isspace(*pos) ) pos++; /* Ignore leading whitespace */
+
+ if ( ! *pos )
+ return ACT_ERR; /* Syntax error */
+
+ for ( act = ACT_CAT, act_str = act_strs ; *act_str ; act++, act_str++ )
+ if ( strncmp(pos, *act_str, i = strlen(*act_str)) == 0 )
+ {
+ pos += i;
+ break;
+ }
+
+ if ( ! *act_str )
+ {
+#if DEBUG > 3
+ fprintf(stderr,"No match\n");
+#endif
+ return ACT_ERR; /* Unknown action */
+ }
+
+ if ( *pos && !isspace(*pos) )
+ {
+#if DEBUG > 3
+ fprintf(stderr,"Garbage at end: %s\n", pos);
+#endif
+ return ACT_ERR; /* Garbage after action name */
+ }
+
+ if ( cmd )
+ {
+ while ( isspace(*pos) ) pos++; /* Skip leading whitespace again */
+ *cmd = pos;
+ }
+
+ return act;
+}
+
diff --git a/plfilters/dj550c-filter.x b/plfilters/dj550c-filter.x
new file mode 100644
index 0000000..cd396a3
--- /dev/null
+++ b/plfilters/dj550c-filter.x
@@ -0,0 +1,25 @@
+# -*- perl -*-
+#
+# Magicfilter definitions file for the HP DeskJet 550c
+#
+
+$primary = 'HP DeskJet 550C';
+@alsofor = ( 'HP DeskJet 560C' );
+
+$dpi = 300;
+$color = 1;
+
+@gs_devs = ('cdj550', 'djet550c', 'cdj500', 'cdj500c', 'djet500', 'deskjet');
+
+$pcl_ver = 3.0;
+$handle_pcl = 'cat';
+$handle_text = "cat\t\\eE\\e&k2G\\e(0N\t\\eE";
+$latin1_ok = $ascii_ok = 1;
+
+sub endrules {
+ print <<EOF;
+
+# Wild guess: ESC begins a PCL sequence
+0 \\e $handle_pcl
+EOF
+}
diff --git a/plfilters/filters1.h b/plfilters/filters1.h
new file mode 100644
index 0000000..cfeb5bf
--- /dev/null
+++ b/plfilters/filters1.h
@@ -0,0 +1,28 @@
+/* filters/filters1.h. Generated automatically by configure. */
+/*
+ * Fill-in-the-blank file for configure; included from filters.xh
+ *
+ * Note that only #define statements in this file are actually processed!
+ */
+
+/* define if ditroff works as expected */
+#define DITROFF_WORKS 1
+
+/* define if zcat is really gzip */
+#define ZCAT_IS_GZIP 1
+
+/* define if we have a way to access the standard file handles through
+ a pathname */
+
+/* /dev/stdin, /dev/stdout (FSSTND compliant Linux) */
+#define HAVE_DEV_STDIN 1
+#define HAVE_DEV_STDOUT 1
+
+/* /dev/fd/0, /dev/fd/1 (System V) */
+#define HAVE_DEV_FD_0 1
+#define HAVE_DEV_FD_1 1
+
+/* /proc/self/fd/0, /proc/self/fd/1 (Linux, even if noncompliant)
+ The path name is way ugly, though... */
+#define HAVE_PROC_SELF_FD_0 1
+#define HAVE_PROC_SELF_FD_1 1
diff --git a/plfilters/filters2.h b/plfilters/filters2.h
new file mode 100644
index 0000000..dc7391e
--- /dev/null
+++ b/plfilters/filters2.h
@@ -0,0 +1,58 @@
+/* filters/filters2.h. Generated automatically by configure. */
+/* filters2.h.in: This file was automatically generated by mkfilterhin */
+#define HAVE_GHOSTSCRIPT 1
+#define PATH_GHOSTSCRIPT "/usr/bin/gs"
+#define HAVE_PDF2PS 1
+#define PATH_PDF2PS "/usr/bin/pdf2ps"
+#define HAVE_GROG 1
+#define PATH_GROG "/usr/bin/grog"
+#define HAVE_GROFF 1
+#define PATH_GROFF "/usr/bin/groff"
+#define HAVE_DITROFF 1
+#define PATH_DITROFF "/usr/bin/gtroff"
+#define HAVE_GROPS 1
+#define PATH_GROPS "/usr/bin/grops"
+#define HAVE_GRODVI 1
+#define PATH_GRODVI "/usr/bin/grodvi"
+#define HAVE_GROTTY 1
+#define PATH_GROTTY "/usr/bin/grotty"
+#define HAVE_GROLJ4 1
+#define PATH_GROLJ4 "/usr/bin/grolj4"
+#define HAVE_GZIP 1
+#define PATH_GZIP "/bin/gzip"
+#define HAVE_ZCAT 1
+#define PATH_ZCAT "/bin/zcat"
+#define HAVE_UNCOMPRESS 1
+#define PATH_UNCOMPRESS "/usr/bin/uncompress"
+#define HAVE_DVIPS 1
+#define PATH_DVIPS "/usr/bin/dvips"
+#define HAVE_PNMTOPS 1
+#define PATH_PNMTOPS "/usr/local/bin/pnmtops"
+#define HAVE_GIFTOPPM 1
+#define PATH_GIFTOPPM "/usr/local/bin/giftopnm"
+#define HAVE_DJPEG 1
+#define PATH_DJPEG "/usr/bin/djpeg"
+/* #undef HAVE_PNGTOPNM */
+/* #undef PATH_PNGTOPNM */
+#define HAVE_SGITOPNM 1
+#define PATH_SGITOPNM "/usr/local/bin/sgitopnm"
+/* #undef HAVE_TOPS */
+/* #undef PATH_TOPS */
+/* #undef HAVE_SGITOPS */
+/* #undef PATH_SGITOPS */
+#define HAVE_TIFFTOPNM 1
+#define PATH_TIFFTOPNM "/usr/local/bin/tifftopnm"
+#define HAVE_BMPTOPPM 1
+#define PATH_BMPTOPPM "/usr/local/bin/bmptoppm"
+#define HAVE_RASTTOPNM 1
+#define PATH_RASTTOPNM "/usr/local/bin/rasttopnm"
+#define HAVE_NENSCRIPT 1
+#define PATH_NENSCRIPT "/usr/local/bin/nenscript"
+/* #undef HAVE_A2X */
+/* #undef PATH_A2X */
+/* #undef HAVE_A2PS */
+/* #undef PATH_A2PS */
+#define HAVE_FIG2DEV 1
+#define PATH_FIG2DEV "/usr/X11R6/bin/fig2dev"
+#define HAVE_SENDMAIL 1
+#define PATH_SENDMAIL "/usr/lib/sendmail"
diff --git a/plfilters/genmagicfilter b/plfilters/genmagicfilter
new file mode 100755
index 0000000..ee589b6
--- /dev/null
+++ b/plfilters/genmagicfilter
@@ -0,0 +1,26 @@
+# -*- perl -*-
+#
+# magicfilter generation script
+#
+# Generates magicfilters based on the input database
+#
+
+if ( ! defined($mflibpath) ) {
+ $mflibpath = '.';
+}
+
+if ( $#ARGV != 0 ) {
+ print STDERR "Usage: $0 printer\n";
+ exit 1;
+}
+
+($printer) = @ARGV;
+
+if ( ! -f "${mflibpath}/$printer-filter.x" ) {
+ print "$0: Printer type $printer unknown\n";
+ exit 1;
+}
+
+do "${mflibpath}/$printer-filter.x";
+do "${mflibpath}/stdconv.xh";
+
diff --git a/plfilters/h2xh.pl b/plfilters/h2xh.pl
new file mode 100644
index 0000000..8f219e8
--- /dev/null
+++ b/plfilters/h2xh.pl
@@ -0,0 +1,15 @@
+# -*- perl -*-
+#
+# Convert a .h file generated by autoconf to an .xh file for inclusion
+# in a perl script
+#
+
+print "# This file is automatically generated by h2xh\n";
+while ( defined($line = <>) ) {
+ if ( $line =~ /^\#define\s+PATH_([A-Z0-9_]+)\s+\"([^\"]+)\"/ ) {
+ $prog = $1;
+ $path = $2;
+ $prog =~ tr/A-Z/a-z/;
+ print "\$path_${prog} = \'${path}\';\n";
+ }
+}
diff --git a/plfilters/mfconfig.xh b/plfilters/mfconfig.xh
new file mode 100644
index 0000000..53add1f
--- /dev/null
+++ b/plfilters/mfconfig.xh
@@ -0,0 +1,2 @@
+$path_magicfilter = '/usr/local/bin/magicfilter';
+$mfversion = '1.3';
diff --git a/plfilters/mfconfig.xh.in b/plfilters/mfconfig.xh.in
new file mode 100644
index 0000000..0cee3e2
--- /dev/null
+++ b/plfilters/mfconfig.xh.in
@@ -0,0 +1,57 @@
+/* filters2.h.in: This file was automatically generated by mkfilterhin */
+#undef HAVE_GHOSTSCRIPT
+#undef PATH_GHOSTSCRIPT
+#undef HAVE_PDF2PS
+#undef PATH_PDF2PS
+#undef HAVE_GROG
+#undef PATH_GROG
+#undef HAVE_GROFF
+#undef PATH_GROFF
+#undef HAVE_DITROFF
+#undef PATH_DITROFF
+#undef HAVE_GROPS
+#undef PATH_GROPS
+#undef HAVE_GRODVI
+#undef PATH_GRODVI
+#undef HAVE_GROTTY
+#undef PATH_GROTTY
+#undef HAVE_GROLJ4
+#undef PATH_GROLJ4
+#undef HAVE_GZIP
+#undef PATH_GZIP
+#undef HAVE_ZCAT
+#undef PATH_ZCAT
+#undef HAVE_UNCOMPRESS
+#undef PATH_UNCOMPRESS
+#undef HAVE_DVIPS
+#undef PATH_DVIPS
+#undef HAVE_PNMTOPS
+#undef PATH_PNMTOPS
+#undef HAVE_GIFTOPPM
+#undef PATH_GIFTOPPM
+#undef HAVE_DJPEG
+#undef PATH_DJPEG
+#undef HAVE_PNGTOPNM
+#undef PATH_PNGTOPNM
+#undef HAVE_SGITOPNM
+#undef PATH_SGITOPNM
+#undef HAVE_TOPS
+#undef PATH_TOPS
+#undef HAVE_SGITOPS
+#undef PATH_SGITOPS
+#undef HAVE_TIFFTOPNM
+#undef PATH_TIFFTOPNM
+#undef HAVE_BMPTOPPM
+#undef PATH_BMPTOPPM
+#undef HAVE_RASTTOPNM
+#undef PATH_RASTTOPNM
+#undef HAVE_NENSCRIPT
+#undef PATH_NENSCRIPT
+#undef HAVE_A2X
+#undef PATH_A2X
+#undef HAVE_A2PS
+#undef PATH_A2PS
+#undef HAVE_FIG2DEV
+#undef PATH_FIG2DEV
+#undef HAVE_SENDMAIL
+#undef PATH_SENDMAIL
diff --git a/plfilters/mfpaths.xh b/plfilters/mfpaths.xh
new file mode 100644
index 0000000..adcf4c2
--- /dev/null
+++ b/plfilters/mfpaths.xh
@@ -0,0 +1,24 @@
+# This file is automatically generated by h2xh
+$path_ghostscript = '/usr/bin/gs';
+$path_pdf2ps = '/usr/bin/pdf2ps';
+$path_grog = '/usr/bin/grog';
+$path_groff = '/usr/bin/groff';
+$path_ditroff = '/usr/bin/gtroff';
+$path_grops = '/usr/bin/grops';
+$path_grodvi = '/usr/bin/grodvi';
+$path_grotty = '/usr/bin/grotty';
+$path_grolj4 = '/usr/bin/grolj4';
+$path_gzip = '/bin/gzip';
+$path_zcat = '/bin/zcat';
+$path_uncompress = '/usr/bin/uncompress';
+$path_dvips = '/usr/bin/dvips';
+$path_pnmtops = '/usr/local/bin/pnmtops';
+$path_giftoppm = '/usr/local/bin/giftopnm';
+$path_djpeg = '/usr/bin/djpeg';
+$path_sgitopnm = '/usr/local/bin/sgitopnm';
+$path_tifftopnm = '/usr/local/bin/tifftopnm';
+$path_bmptoppm = '/usr/local/bin/bmptoppm';
+$path_rasttopnm = '/usr/local/bin/rasttopnm';
+$path_nenscript = '/usr/local/bin/nenscript';
+$path_fig2dev = '/usr/X11R6/bin/fig2dev';
+$path_sendmail = '/usr/lib/sendmail';
diff --git a/plfilters/stdconv.xh b/plfilters/stdconv.xh
new file mode 100644
index 0000000..3aa3089
--- /dev/null
+++ b/plfilters/stdconv.xh
@@ -0,0 +1,588 @@
+# -*- perl -*-
+#
+# The magicfilter standard conversions library
+#
+# The bulk of the magicfilter script is generated from this file
+#
+
+do "${mflibpath}/mfconfig.xh";
+do "${mflibpath}/mfpaths.xh";
+
+#
+# Standard prologue
+#
+print <<EOF;
+#! $path_magicfilter
+#
+# Magicfilter configuration file for ${primary};
+# created from printer database included with magicfilter version ${mfversion}.
+EOF
+if ( @alsofor ) {
+ print "#\n# This configuration file also supports:\n";
+ foreach $pr ( @alsofor ) {
+ print "#\t\t${pr}\n";
+ }
+}
+print <<EOF;
+#
+# This file has been customized to your system.
+#
+EOF
+
+#
+# Find aliases for file handles, if available
+# (Note: the Linux ones have a severe misfeature, but are enough for our use)
+#
+if ( -d '/dev/fd' ) {
+ $anyfh = '/dev/fd/%d';
+} elsif ( -d '/proc/self/fd' ) {
+ $anyfh = '/proc/self/fd/%d';
+} else {
+ undef $anyfh;
+}
+
+if ( -r '/dev/stdin' ) {
+ $stdin = '/dev/stdin';
+} elsif ( $anyfh ) {
+ $stdin = sprintf($anyfh, 0);
+} else {
+ undef $stdin;
+}
+
+if ( -w '/dev/stdout' ) {
+ $stdout = '/dev/stdout';
+} elsif ( $anyfh ) {
+ $stdout = sprintf($anyfh, 1);
+} else {
+ undef $stdout;
+}
+
+#
+# Find an appropriate alias for zcat
+#
+if ( $path_gzip ) {
+ $zcat = "$path_gzip -cdq";
+} elsif ( $path_uncompress ) {
+ $zcat = "$path_uncompress -c";
+} elsif ( $path_zcat ) {
+ $zcat = $path_zcat;
+}
+
+#
+# Normalize dpi
+#
+$xdpi = $dpi if ( $dpi && !$xdpi );
+$ydpi = $dpi if ( $dpi && !$ydpi );
+
+#
+# GhostScript - find the optimum driver (doesn't necessarily mean we'll
+# use it, though)
+#
+if ( $path_ghostscript && @gs_devs ) {
+ # @gs_devs is a list of GhostScript drivers in declining order of
+ # preference, set by the printer select script
+ #
+ # Probe GhostScript to find out what this particular version can do
+ #
+
+ open(GHOSTSCRIPT, "$path_ghostscript -help |") ||
+ die "$0: could not execute $path_ghostscript: ";
+
+ %gs_dev = ();
+ %gs_lang = ();
+
+ $state = 0;
+
+ while ( $line = <GHOSTSCRIPT> ) {
+ if ( $line =~ /^Available devices:/ ) {
+ $state = 1;
+ } elsif ( $line =~ /^Language interpreters:/ ) {
+ $state = 2;
+ } elsif ( $line =~ /^[^\t]/ ) {
+ $state = 0;
+ } elsif ( $state == 1 ) {
+ foreach $dev ( split(/\s+/, $line) ) {
+ $gs_dev{$dev}++ if ( $dev );
+ }
+ } elsif ( $state == 2 ) {
+ foreach $lang ( split(/\s+/, $line) ) {
+ $gs_lang{$lang}++ if ( $lang );
+ }
+ }
+ }
+ close(GHOSTSCRIPT);
+ $gs_lang{'PostScript'}++ if ( ! %gs_lang );
+
+ undef $gs_device;
+ foreach $dev (@gs_devs) {
+ if ( $gs_dev{$dev} ) {
+ $gs_device = $dev;
+ last;
+ }
+ }
+ unless ( defined($gs_dpi) ) {
+ if ( $xdpi != $ydpi ) {
+ $gs_dpi = "-r${xdpi}x${ydpi}";
+ } else {
+ $gs_dpi = "-r${dpi}";
+ }
+ }
+}
+
+#
+# PostScript
+#
+$ps_ok = 0;
+if ( $native_ps ) {
+ $ps_ok = 1;
+ $handle_ps = 'postscript'; # Sent to a native PostScript printer
+ $psact = 'filter'; # Don't reprocess PostScript
+ $fpsact = 'ffilter';
+} elsif ( $handle_ps ) {
+ $ps_ok = 1;
+ $psact = 'pipe'; # Process PostScript
+ $fpsact = 'fpipe';
+} elsif ( $gs_device && $gs_lang{'PostScript'}) {
+ if ( $gs_device ) {
+ $handle_ps = "filter\t$path_ghostscript -q -dSAFER -dNOPAUSE -dNODISPLAY \\\n".
+ "\t\t\t\t${gs_dpi} -sDEVICE=${gs_device} ${gs_opt} \\\n".
+ "\t\t\t\t-sOutputFile=- -";
+ $ps_ok = 1;
+ $psact = 'pipe';
+ $fpsact = 'fpipe';
+ }
+ $ps_level2 = $gs_lang{'PostScriptLevel2'};
+}
+
+if ( ! $ps_ok ) {
+ $handle_ps = "reject\tCannot print PostScript on this printer.";
+}
+
+if ( ! $ps_ok ) {
+ print <<EOF;
+# However, since your system apparently has no means for converting
+# PostScript, which your printer does not handle natively, most formats
+# will probably result in rejects.
+#
+EOF
+}
+
+print <<EOF;
+
+# PostScript
+0 %! $handle_ps
+0 \\004%! $handle_ps
+EOF
+
+#
+# Adobe Portable Document Format (PDF/Acrobat)
+#
+
+$pdf_ok = 0;
+if ( $handle_pdf ) {
+ # We're set!
+ $pdf_ok = 1;
+} elsif ( $gs_device && $gs_lang{'PDF'} ) {
+ # If we're using GhostScript, use it to generate PDF as well, if
+ # GhostScript knows PDF (we do, however, use ffilter for PDF)
+ $handle_pdf = "ffilter\t$path_ghostscript -q -dSAFER -dNOPAUSE -dNODISPLAY \\\n".
+ "\t\t\t\t${gs_dpi} -sDEVICE=${gs_device} ${gs_opt} \\\n".
+ "\t\t\t\t-sOutputFile=- -";
+ $pdf_ok = 1;
+} elsif ( $ps_ok ) {
+ if ( $path_acroread ) {
+ if ( $ps_level2 ) {
+ $handle_pdf = "$fpsact\t$path_acroread -toPostScript -level2";
+ } else {
+ $handle_pdf = "$fpsact\t$path_acroread -toPostScript";
+ }
+ $pdf_ok = 1;
+ } elsif ( $path_pdftops ) {
+ if ( $stdout ) {
+ $handle_pdf = "$fpsact\t$path_pdftops $FILE $stdout";
+ } else {
+ $handle_pdf ="$fpsact\t$path_pdftops \$FILE /tmp/out\$\$.ps; \\\n".
+ "\t\t\t\tcat /tmp/pdfout\$\$.ps; rm /tmp/out\$\$.ps";
+ }
+ $pdf_ok = 1;
+ } elsif ( $path_ghostscript && $gs_lang{'PDF'} ) {
+ if ( $stdout ) {
+ $handle_pdf = "$fpsact\t$path_ghostscript -q -dSAFER -dNOPAUSE -dNODISPLAY \\\n".
+ "\t\t\t\t-sPSFile=$stdout \$FILE -c quit";
+ } else {
+ $handle_pdf = "$fpsact\t$path_ghostscript -q -dSAFER -dNOPAUSE -dNODISPLAY \\\n".
+ "\t\t\t\t-sPSFile=/tmp/pdfout\$\$.ps \$FILE -c quit ; \\\n".
+ "\t\t\t\tcat /tmp/pdfout\$\$.ps; rm /tmp/pdfout\$\$.ps";
+ }
+ $pdf_ok = 1;
+ }
+}
+
+if ( ! $pdf_ok ) {
+ $handle_pdf = "reject\tCannot print PDF (Adobe Acrobat) files on \\\n".
+ "\t\t\t\tthis printer.";
+}
+
+print <<EOF;
+
+# Adobe PDF (Acrobat)
+0 %PDF $handle_pdf
+EOF
+
+#
+# ASCII/Latin1 text generation (actual entry goes last)
+#
+# FIXME: Paper size selection
+#
+if ( ! $handle_text ) {
+ $latin1_ok = 0;
+ if ( $path_enscript ) {
+ $handle_text = "$psact\t$path_enscript -B -p-";
+ $latin1_ok = 1;
+ } elsif ( $path_a2x ) {
+ $handle_text = "$psact\t$path_a2x -p -dps -man";
+ $latin1_ok = 1;
+ } elsif ( $path_a2ps ) {
+ # Untested!
+ $handle_text = "$psact\t$path_a2ps -p -nh -nn -f12 -b";
+ $latin1_ok = 1;
+ }
+}
+$ascii_ok = $handle_text ? 1 : 0;
+if ( ! $ascii_ok ) {
+ $handle_text = "reject\tCannot print text files on this printer.";
+}
+
+#
+# TeX DVI
+#
+if ( ! $handle_dvi ) {
+ if ( $path_dvips && $ps_ok ) {
+ if ( $xdpi == $ydpi ) {
+ $handle_dvi = "$fpsact\t$path_dvips -D $dpi -R -q -F -f";
+ } else {
+ $handle_dvi = "$fpsact\t$path_dvips -X $xdpi -Y $ydpi -R -q -F -f";
+ }
+ }
+}
+$dvi_ok = $handle_dvi ? 1 : 0;
+if ( ! $dvi_ok ) {
+ $handle_dvi = "reject\tCannot print DVI files on this printer.";
+}
+
+print <<EOF;
+
+# TeX DVI
+0 \\367\\002 $handle_dvi
+EOF
+
+#
+# Compressed data
+#
+if ( $zcat ) {
+ $handle_compress = "pipe\t$zcat";
+} else {
+ $handle_compress = "reject\tCannot print compressed files on this printer.";
+}
+print <<EOF;
+
+# Various compression formats
+0 \\037\\235 $handle_compress
+EOF
+
+if ( $path_gzip ) {
+ print <<EOF;
+0 \\037\\036 pipe $path_gzip -cdq
+0 \\037\\213 pipe $path_gzip -cdq
+0 \\037\\236 pipe $path_gzip -cdq
+0 \\037\\240 pipe $path_gzip -cdq
+EOF
+} else {
+ print <<EOF;
+0 \\037\\036 reject Cannot print packed files on this printer.
+0 \\037\\213 reject Cannot print gzipped files on this printer.
+0 \\037\\236 reject Cannot print frozen files on this printer.
+0 \\037\\240 reject Cannot print SCO LZH files on this printer.
+EOF
+}
+
+#
+# HP PCL/PJL definitions
+#
+if ( $handle_pcl ) {
+ $pcl_ver = 1.0 unless ( $pcl_ver );
+} else {
+ $pcl_ver = 0.0;
+ $handle_pcl = "reject\tCannot print PCL files on this printer.";
+}
+if ( $handle_pjl ) {
+ $pjl_ok = 1;
+} else {
+ $pjl_ok = 0;
+ $handle_pjl = "reject\tCannot print PJL files on this printer.";
+}
+
+#
+# ditroff -- this is probably a kluge, but it works with ghostscript
+#
+if ( $path_grops && $ps_ok ) {
+ print <<EOF;
+0 "x T ps" $psact $path_grops
+EOF
+} else {
+ print <<EOF;
+0 "x T ps" reject Cannot print PostScript ditroff files on this printer.
+EOF
+}
+if ( $path_grodvi && $dvi_ok ) {
+ print <<EOF;
+0 "x T dvi" pipe $path_grodvi
+EOF
+} else {
+ print <<EOF;
+0 "x T dvi" reject Cannot print DVI ditroff files on this printer.
+EOF
+}
+if ( $path_grotty && $ascii_ok ) {
+ print <<EOF;
+0 "x T ascii" pipe $path_grotty
+0 "x T latin1" pipe $path_grotty
+EOF
+} else {
+ print <<EOF;
+0 "x T ascii" reject Cannot print ASCII ditroff files on this printer.
+0 "x T latin1" reject Cannot print Latin-1 ditroff files on this printer.
+EOF
+}
+if ( $path_grolj4 && $pcl_ver >= 5.1 ) {
+ print <<EOF;
+0 "x T lj4" filter $path_grolj4
+EOF
+} else {
+ print <<EOF;
+0 "x T lj4" reject Cannot print LaserJet 4 ditroff files on this printer.
+EOF
+}
+
+#
+# PNM files
+#
+if ( $handle_pnm ) {
+ $pnm_ok = 1;
+} elsif ( $path_pnmtops && $ps_ok ) {
+ $handle_pnm = "$psact\t$path_pnmtops -scale 1000 -dpi $dpi 2>/dev/null";
+ $pnm_ok = 1;
+} else {
+ $handle_pnm = "reject\tCannot print PBM/PGM/PPM files on this printer.";
+ $pnm_ok = 0;
+}
+
+print <<EOF;
+
+# Portable bit-, grey-, and pixmaps
+0 P1\\n $handle_pnm
+0 P2\\n $handle_pnm
+0 P3\\n $handle_pnm
+0 P4\\n $handle_pnm
+0 P5\\n $handle_pnm
+0 P6\\n $handle_pnm
+EOF
+
+#
+# HP PCL/PJL
+#
+print <<EOF;
+
+# HP Printer Control Language (PCL) -- assume start with reset code
+# (pretty much universal)
+0 \\eE\\e $handle_pcl
+
+# HP Printer Job Language
+0 \\e\%-12345X $handle_pjl
+0 "\@PJL" $handle_pjl
+EOF
+
+#
+# GIF images
+#
+$path_giftoppm = $path_giftopnm || $path_giftoppm;
+print <<EOF;
+
+# CompuServe Graphics Interchange Format (GIF)
+EOF
+if ( $path_giftoppm && $pnm_ok ) {
+ print <<EOF;
+0 GIF87a pipe $path_giftoppm 2>/dev/null
+0 GIF89a pipe $path_giftoppm 2>/dev/null
+EOF
+} else {
+ print <<EOF;
+0 GIF87a reject Cannot print GIF images on this printer.
+0 GIF89a reject Cannot print GIF images on this printer.
+EOF
+}
+
+#
+# JFIF (JPEG) images
+#
+print <<EOF;
+
+# JFIF (JPEG) images
+EOF
+if ( $path_djpeg && $pnm_ok ) {
+ print <<EOF;
+0 \\377\\330\\377\\340\\?\\?JFIF\\0 pipe $path_djpeg -pnm
+EOF
+} else {
+ print <<EOF;
+0 \\377\\330\\377\\340\\?\\?JFIF\\0 reject Cannot print JPEG images on this printer.
+EOF
+}
+
+#
+# Portable Network Graphics (PNG) images
+#
+print <<EOF;
+
+# Portable Network Graphics (PNG) images
+EOF
+if ( $path_pngtopnm && $pnm_ok ) {
+ print <<EOF;
+0 \\211PNG\\r\\n\\032\\n pipe $path_pngtopnm 2>/dev/null
+EOF
+} else {
+ print <<EOF;
+0 \\211PNG\\r\\n\\032\\n reject Cannot print PNG images on this printer.
+EOF
+}
+
+#
+# TIFF files (the last two bytes of the "magic" is really a version number; but the magic
+# is just so lame, and as far as I have understood the version number has never changed
+# and never will, so it is part of the magic now!)
+#
+print <<EOF;
+
+# Tagged Image File Format (TIFF)
+EOF
+if ( $path_tifftopnm && $pnm_ok ) {
+ print <<EOF;
+0 MM\\0\\x2a pipe $path_tifftopnm 2>/dev/null
+0 II\\x2a\\0 pipe $path_tifftopnm 2>/dev/null
+EOF
+} else {
+ print <<EOF;
+0 MM\\0\\x2a reject Cannot print TIFF images on this printer.
+0 II\\x2a\\0 reject Cannot print TIFF images on this printer.
+EOF
+}
+
+#
+# Microsoft BMP files (IFF?) -- This is an absolutely idiotic magic...
+#
+print <<EOF;
+
+# Microsoft BMP files
+EOF
+if ( $path_bmptoppm && $pnm_ok ) {
+ print <<EOF;
+0 BM\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\x0c pipe \\
+ $path_bmptoppm 2>/dev/null
+0 BM\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\x40 pipe \\
+ $path_bmptoppm 2>/dev/null
+0 BM\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\x28 pipe \\
+ $path_bmptoppm 2>/dev/null
+EOF
+} else {
+ print <<EOF;
+0 BM\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\x0c reject \\
+ Cannot print BMP images on this printer.
+0 BM\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\x40 reject \\
+ Cannot print BMP images on this printer.
+0 BM\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\?\\x28 reject \\
+ Cannot print BMP images on this printer.
+EOF
+}
+
+#
+# Sun rasterfiles
+#
+print <<EOF;
+
+# Sun rasterfiles
+EOF
+if ( $path_rasttopnm && $pnm_ok ) {
+ print <<EOF;
+0 \\x59\\xa6\\x6a\\x95 pipe $path_rasttopnm 2>/dev/null
+EOF
+} else {
+ print <<EOF;
+0 \\x59\\xa6\\x6a\\x95 reject Cannot print Sun rasterfiles on this printer.
+EOF
+}
+
+print <<EOF;
+
+# SGI Imagelib (IRIS RGB) files
+EOF
+$sgi_cmyk = ( $color ) ? '-cmyk' : '';
+if ( $path_sgitopnm && $pnm_ok ) {
+ print <<EOF;
+0 \\x1\\xda pipe $path_sgitopnm 2>/dev/null
+0 \\xda\\x1 pipe $path_sgitopnm 2>/dev/null
+EOF
+} elsif ( $have_sgitops && $ps_ok ) {
+ print <<EOF;
+0 \\x1\\xda $fpsact $path_sgitops $FILE -cmyk
+0 \\xda\\x1 $fpsact $path_sgitops $FILE -cmyk
+EOF
+} elsif ( $have_tops && $ps_ok && ( -x '/bin/uname' ) &&
+ `/bin/uname` eq "IRIX\n" ) {
+ print <<EOF;
+0 \\x1\\xda $fpsact $path_tops $FILE -cmyk
+0 \\xda\\x1 $fpsact $path_tops $FILE -cmyk
+EOF
+} else {
+ print <<EOF;
+0 \\x1\\xda reject Cannot print SGI RGB files on this printer.
+0 \\xda\\x1 reject Cannot print SGI RGB files on this printer.
+EOF
+}
+
+print <<EOF;
+
+# FIG files; reported by Steven P. Hill <sph\@uscbu.ih.att.com>
+EOF
+if ( $have_fig2dev && $ps_ok ) {
+ print <<EOF;
+0 #FIG pipe $path_fig2dev -Lps -P -l dummy
+EOF
+} else {
+ print <<EOF;
+0 #FIG reject Cannot print FIG files on this printer.
+EOF
+}
+
+print <<'EOF';
+
+#
+# Standard reject rules
+#
+EOF
+
+#
+# If the printer driver has specified any special last-ditch rules, include
+# them here
+#
+eval '&endrules;';
+
+#
+# Default case is text, unless the printer driver has overridden us
+#
+if ( ! $special_default ) {
+ print <<EOF;
+
+# Default case: plain text
+default $handle_text
+EOF
+}