Checkpoint.
diff --git a/src/cmd/postscript/NOTES b/src/cmd/postscript/NOTES
new file mode 100644
index 0000000..fb673ce
--- /dev/null
+++ b/src/cmd/postscript/NOTES
@@ -0,0 +1,32 @@
+ Directory dpost is DWB 3.3 version without UTF changes. dpost.utf is
+ stuff for Plan 9. Both build and install dpost, so only pick one. The
+ makefile I sent (postscript.mk) builds dpost.utf.
+
+ Left READING set to ONEBYTE in common/gen.h. Expect dpost errors unless
+ 'x E UTF' is added to troff output or READING set to UTFENCODING. Easy
+ to make 'x E UTF' anything else too.
+
+ Left RUNELIB defined in common/rune.h so rune.c stuff is used when
+ dpost.utf is built.
+
+ UTF.enc is in directory psencoding. Install and link to Default.enc on
+ Plan 9.
+
+ Carmela requested two new characters: \(bs for backslash and \(dq for
+ double quote. Both are in devLatin1 and devpost tables. Carmela also
+ asked for a bunch of her devpost accent characters in devLatin1. Added
+ them to the end of the devLatin1 tables.
+
+ A word of warning about devLatin1. Carmela, Peter and others complained
+ about - and hyphens being too long in the Latin1 fonts. I used Abode's
+ choice but nobody liked it. New devLatin1 tables use a smaller character
+ for hy. Looks better (I guess) but a width change affects line and page
+ breaks!! Not sure what you want to do. Complaints on this one go to
+ npn and carmela!!!
+
+ Didn't take your suggested pathname change in download. Didn't want to
+ risk breaking Unix 4.0 lp. What's there is bogus but was only for Unix
+ 4.0. The -r option accomplishes something similiar but needs a full path.
+
+ postio.mk is very different and not tested on V9.
+
diff --git a/src/cmd/postscript/README b/src/cmd/postscript/README
new file mode 100644
index 0000000..7deebb0
--- /dev/null
+++ b/src/cmd/postscript/README
@@ -0,0 +1,179 @@
+Stuff appears to work, but it's obviously not well tested. I fully
+expect several iterations before things are correct!! Make sure you
+can back this out quickly.
+
+This code supports UTF encoding. Directory dpost.utf is a version that
+reads UTF encoded files. Directory dpost is DWB 3.3 source and should be
+close to what you're currently using. Main source code changes were in
+dpost.utf (files font.h, font.c, and dpost.c). Select either dpost or
+dpost.utf in TARGETS in postscript.mk. Both build and install a program
+called dpost!!
+
+dpost.utf is more general and includes code that lets it read either
+format. Only catch is troff must tell it (with x E UTF) that the file
+is UTF and troff currently doesn't output encoding info, so you're
+stuck with two post-processors!
+
+Added common/rune.h and common/rune.c so code can be compiled elsewere.
+Both files are only used by dpost. Remove RUNELIB in commmon/rune.h if
+fullrune(), chartorune(), and runetochar() are available on your system.
+You will also need to set READING in common/gen.h. It controls how dpost
+(from dpost.utf) reads troff output. It should be UTFENCODING on Plan 9
+and ONEBYTE elsewhere. If troff includes encoding hint (x E UTF) then
+READING selects the default which sould be ONEBYTE.
+
+Leave WRITING (in common/gen.h) set to ONEBYTE. It only controls dpost
+output and dpost (right now) does not work 100% with UTF.enc. Fix should
+be easy, but I don't have time now.
+
+Other translators passed bytes through so only needed slightly modified
+proglogues and a new encoding scheme (psencoding/UTF.enc). It works for
+Latin1, but still needs a bit more attention. Prologue changes were easy
+and only involved adding lines like,
+
+	/show {show} bind def
+	/stringwidth {stringwidth} bind def
+
+Guarantees text procedures used in prologues aren't operators and can be
+successfully redefined in UTF.enc. Unbinding means a small but probably
+not noticeable speed penalty. You may not want to include those changes
+on other system.
+
+-------------
+Major Changes
+-------------
+
+See the VERSION file.
+
+-------------------
+Tuning The Makefile
+-------------------
+
+Source files, man pages, and low level makefiles can all be updated
+to reflect settings in postscript.mk in one simple step (described
+later). In most cases you only need to edit file postscript.mk.
+
+First save a copy of file postscript.mk. Then adjust the following
+definitions in file postscript.mk:
+
+  SYSTEM    best match for your version of Unix. Current choices for
+	    SYSTEM are:
+
+			SYSV	- System V
+			V9	- Ninth Edition
+			BSD4_2	- Berkeley (eg. Sun)
+
+	    Controls conditional compilation in a few places.
+
+  GROUP	    group assigned to all installed files
+
+  OWNER	    owner of everything that's installed
+
+  BINDIR    dpost and picpack go here. All other programs go in POSTBIN.
+	    BINDIR must already exist - it will not be created during an
+	    install.
+
+  HOSTDIR   hostresident font directory for PostScript printers. Only
+	    used in the font download program.
+
+  FONTDIR   width table directory - for troff and most postprocessors
+
+  MAN1DIR   command manpages. A command and its manpage are installed
+	    together - there's no easy way to avoid it. Setting MAN1DIR
+	    to an existing temporary directory (e.g. /tmp) means an
+	    install will work but manpages won't go anywhere permanent.
+	    MAN1DIR must already exist - it will not be created during
+	    an install.
+
+  POSTBIN   where most PostScript support programs go. dpost and picpack
+	    the exceptions.
+
+  POSTLIB   prologues and miscellaneous PostScript files. Primarily for
+	    the programs that live in POSTBIN.
+
+  CFLGS	    common compiler options - used to build CFLAGS in the low
+	    level makefiles. CLFGS and LDFLGS are best set on the make
+	    command line.
+
+  LDFLGS    common link editor options - used to build LDFLAGS in the
+	    low level makefiles. LDFLGS and CFLGS are best set on the
+	    make command line.
+
+  DKHOST    set it to TRUE to compile the DKHOST Datakit support code
+	    in postio. Temporarily resets SYSTEM to SYSV if DKHOST is
+	    TRUE and SYSTEM is BSD4_2. Ignored if SYSTEM is not SYSV
+	    or BSD4_2.
+
+  DKSTREAMS enables streams based DKHOST support in postio when DKHOST
+	    is TRUE and SYSTEM is SYSV or BSD4_2. Choices are TRUE,
+	    FALSE, or a stream module name (e.g. dknetty or dkty). TRUE
+	    selects dknetty. Newer systems may expect dkty.
+
+  ROUNDPAGE must only be set to TRUE or FALSE. TRUE means PostScript
+	    translators include code that maps clipping path dimensions
+	    into known paper sizes.
+
+  TARGETS   the default list of what's built by make. Each target must
+	    be the name of a source directory. A target that names a
+	    non-existent source directory is ignored. Setting TARGETS
+	    on the make command line overrides the default list.
+
+-------------------
+Updating The Source
+-------------------
+
+Whenever file postscript.mk changes you should update source files,
+man pages, and low level makefiles by typing,
+
+	make -f postscript.mk changes
+
+------------------------
+More System Dependencies
+------------------------
+
+The package has been compiled and tested on System V and Ninth Edition
+Unix Systems and on Sun workstations. Most differences are handled via
+the SYSTEM definition in postscript.mk. Problems that remain are:
+
+  SYSV - System V
+    Use the native compiler if you're on an internal System V UTS
+    machine.
+
+  V9 - Ninth or Tenth Edition
+    chown is in /etc and chgrp no longer exists - it's been folded into
+    the chown command. You may be forced to build a simple chgrp shell
+    script (put it in your bin) that calls chown. If you're not superuser
+    set OWNER to your login name and GROUP to your group id.
+
+  BSD4_2 - Sun Workstations
+    Use the Bourne shell. chown is should be in /usr/etc. Add /usr/etc
+    to your PATH and export PATH. If you're not superuser set OWNER to
+    your login name and GROUP to your group id.
+
+----------------------
+Installing The Package
+----------------------
+
+To build (but not install) the default package (i.e. everything named by
+TARGETS in postscript.mk) type,
+
+	make -f postscript.mk all
+
+To build and install the package type,
+
+	make -f postscript.mk all install
+
+After the package is installed use,
+
+	make -f postscript.mk clobber
+
+to delete binary files and compiled programs from the source directories.
+
+To select part of the package define TARGETS on the command line. For
+example,
+
+	make -f postscript.mk TARGETS="dpost devpost" all install
+
+builds and installs dpost and the PostScript font tables. Quotes hide
+white space from the shell.
+
diff --git a/src/cmd/postscript/VERSION b/src/cmd/postscript/VERSION
new file mode 100644
index 0000000..6fb4722
--- /dev/null
+++ b/src/cmd/postscript/VERSION
@@ -0,0 +1,372 @@
+------------------------
+Version 3.3.2   7/7/92
+------------------------
+
+ 1: Added UTF support for Plan 9. Only signigficant source code changes were
+    in dpost.utf (font.h, font.c, dpost.c). Added common/rune.[hc] so code
+    can be compiled elsewere. Remove RUNELIB in commmon/rune.h if fullrune(),
+    chartorune(), and runetochar() are available on your system. Original
+    DWB 3.3 dpost source is in directory dpost. You should select dpost or
+    dpost.utf in postscript.mk. Both compile and install a program called
+    dpost so don't pick both!
+
+ 2: dpost can read old or UTF troff output. Default is whatever is assigned
+    to READING (file common/gen.h). You get one or the other, unless troff
+    tells dpost what encoding to use (currently x E UTF).
+
+ 3: Most other translators passed bytes through and so only needed slightly
+    modified proglogues and a new encoding scheme (psencoding/UTF.enc). It
+    works for Latin1, but still needs a bit more attention. Prologue changes
+    were easy and only involved adding lines like,
+
+	/show {show} bind def
+	/stringwidth {stringwidth} bind def
+
+    Guarantees text procedures used in prologues aren't operators and can be
+    successfully redefined in UTF.enc. Unbinding means a small but probably
+    not noticeable speed penalty. You may not want to include those changes
+    on other system.
+
+ 4: Operator redefinitions means dpost should work in it's own dictionary
+    (rather than userdict). Not implemented yet, but should be easy. Only
+    potential problem is with picture inclusion when dpost reads UTF.enc.
+
+------------------------
+Version 3.3.2   5/15/92
+------------------------
+
+ 1: postio now outputs all unrecognized status reports - primarly for spooler
+    accounting purposes.
+
+ 2: The makefiles also enable the selection of alternate stream module names
+    for streams based DKHOST support in postio.
+
+ 3: dpost now assumes the optional fifth token in a font mounting command
+    (e.g. x font 2 R /usr/me/font/R) is the full pathname of the font. troff
+    outputs the pathname when a .fp request contains a third argument that
+    begins with a / as in .fp 1 R /usr/me/font/R.
+
+ 4: By request Latin1's - character has been changed from minus to the smaller
+    hyphen character. Added \(dq and \(bs (for " and \ characters) to devpost
+    and devLatin1 tables. Also added \(!! and \(?? to devpost tables.
+
+ 5: Helvetica-Light and Helvetica-LightOblique tables are included as HL and
+    HK in devpost and devLatin1, even though fonts aren't generally available.
+    Also copy H to HM during an install of devpost and devLatin1 tables.
+
+ 6: LH is a horizontally arranged color Lucent logo with text which replaces the AT&T logo.
+    LV is a vertically arranged monochrome AT&T logo with text.
+    FA is a horizontally arranged monochrome Lucent logo with text (low res.).
+	L1 is a monochrome AT&T logo, no text.
+	LA is a monochrome AT&T text.
+
+ 7: Included L1 and LA outlines in devpost and devLatin1. Adjusted LA scaling
+    so size of "AT&T" matches what's in LV. Original PostScript came
+    from Matthijs Melchior.
+
+ 8: Included the "symmetric clippath" version of roundpage.ps as Nroundpage.ps
+    in directory postscript/psfiles. Move it to roundpage.ps if you want it to
+    be the default.
+
+ 9: Added a few lines of code to dpost for handling current implementation of
+    the portrait/landscape mode macros.
+
+10: The man page for download now documents the -r option and notes that -p
+    is for Unix 4.0 lp.
+
+------------------------
+Version 3.3.1   4/30/91
+------------------------
+
+ 1: buildtables stuff has been cleaned up and is now a user level command.
+    Uses shell.lib files that are installed with font tables. The devpost
+    tables were built on a version 47.0 PS-810. The devLatin1 tables were
+    built on a version 51.7 PS-820.
+
+ 2: The devLatin1 tables provide support for the ISO Latin1 alphabet on
+    PostScript printers.
+
+ 3: All translators support different text font encoding schemes using the
+    -E option and *.enc files installed in POSTLIB. The ISO Latin 1 alphabet
+    is supported with file /usr/lib/postscript/Latin1.enc.
+
+ 4: printfont prints a table of the available (encoded) characters in one
+    or more PostScript fonts. It also understands the -E option.
+
+ 5: grabit and hardcopy are two new programs that may be of interest to the
+    more serious PostScript programmer. grabit resembles ==, but produces
+    output that's usally easier to read. hardcopy redirects output from
+    PostScript file output operators (or procedures) to paper. It's useful
+    if you don't have direct access to a printer.
+
+ 6: Prologues and programs are stored together. Other common PostScript files
+    are now in the psfiles directory.
+
+------------------------
+Verions 3.3	4/16/90
+------------------------
+
+ 1: The package is now included in DWB. Version numbers are a bit misleading.
+    The one in postscript.mk refers to the DWB package.
+
+ 2: dpost (and troff) now read ASCII font tables. makedev and the old binary
+    format are gone.
+
+ 3: The devpost directory came directly from the DWB package. The font tables
+    originally distributed with this package are in directory devopost. They
+    are not installed. If possible we recommend you use the devpost tables.
+    The old tables can be installed by adding devopost to the TARGETS list in
+    file postscript.mk.
+
+ 4: dpost recognizes two new fields in font tables. Entries for the full
+    PostScript font look like,
+
+		fontname Times-Roman
+
+    The fontname field is helps manage host resident fonts, the DocumentFonts
+    comment, and is used to define font name abbreviations like the ones in
+    dpost.ps. A font table entry that looks like,
+
+		named in prologue
+
+    disables the runtime abbreviation for the font - dpost assumes it's already
+    in the prologue.
+
+ 5: Extra font tables included in DWB 3.0's devpost font collection are in
+    directory devpost.add. They included here, but should probably not be
+    used.
+
+ 6: Bracket building has been fixed and tested on a wide range of PostScript
+    printers. It will likely still not work on many clones. Real problem
+    appears to be with Adobe's braceleftbt character.
+
+ 7: Most of the special tuning code for device emulation has been removed.
+    Emulation still works, but there may be cases where it's not as good as
+    earlier versions.
+
+ 8: Several problems with color and reverse video printing have been fixed.
+
+ 9: buildtables directory has been cleanup up. The template files in directory
+    buildtables/devpost.data were used to build the devpost tables.
+
+10: postplot and download are two new programs. postplot is for the System V
+    plot package only. Both were written for the Unix 4.0 lp package.
+
+11: postgif is also relatively new - it came from Chi Choy.
+
+12: The translators now rotate clockwise when printing in landscape mode. If
+    you want the old behavior set ROTATION to -1 in postscript.mk.
+
+13: forms.ps has been cleaned up some. Better behavior when you print 2
+    landscape pages on one sheet.
+
+14: Handling of Datakit code for System V has been changed some. Makefiles
+    now expect to find libdk.a and dk.h in standard places (e.g /usr/lib and
+    /usr/include). Set DKHOST to TRUE in postscript.mk to get Datakit support
+    on System V.
+
+    If you're stuck and need to have things behave as they did in the past
+    take a look at file postio/postio.mk. Define DKHOSTDIR and uncomment
+    three lines and the behavior should be close to what it was.
+
+15: Picture inclusion and color macros are gone. They're included in the DWB
+    package, and not here.
+
+------------------------
+Version 3.2	11/27/89
+------------------------
+
+ 1: Implemented height and slant requests in dpost.
+
+ 2: Modified the behavior of all translators so save objects are no longer left
+    on the stack. The original implementation was a mistake and occasionally
+    (e.g. picture inclusion with forms.ps) resulted in invalid restores.
+
+ 3: Fixed the mistake in the external declaration of mesg in postio/slowsend.c.
+
+ 4: The malloc() call in postdmd (routine dimensions()) is only made if patterns
+    is positive.
+
+ 5: Changed definition of De in draw.ps so savematrix is loaded with the CTM
+    whenever De is executed. Original implementation didn't work with forms.ps
+    because the CTM is changed with each page image. (4/29/89)
+
+ 6: Flush stdout when postio is invoked with the -t option - just convenient
+    not necessary. (4/30/89)
+
+ 7: Included a man page for the picture inclusion macros - file man/mpictures.5.
+    (5/6/89)
+
+ 8: Added BoundingBox code to dpost - still needs to go in other translators.
+    Most of the work is done in common/bbox.c. (5/7/89)
+
+ 9: Fiddled with the bracket building stuff in dpost.ps so things finally look
+    decent. Was particularly bad on the typesetter.
+
+10: dpost now generates a PageBoundingBox comment and ps_include.c accepts
+    the comment. Added -B option to enable/disable the BoundingBox calculations.
+    -Bon to enable and -Boff to disable. On by default now, but that may change.
+    Add similar code to the rest of the translators (6/20/89).
+
+11: Fixed ps_include.c so it properly handles %%BeginGlobal and %%EndGlobal.
+    Added braces and compare page.start to page.end instead of 0.
+
+12: Added xymove(hpos, vpos) for \X'PS ...' request - near the end of devcntrl().
+    Must output position info for following PostScript.
+
+13: Added a call to endtext() immediately before the oput() call for \N'...'
+    requests. Without it spacing often messed up with -e2 but not -e0.
+
+------------------------
+Version 3.1	11/15/88
+------------------------
+
+ 1: postio can run as one or two processes (-R option) and can establish an
+    interactive connection with a postscript printer (-i option). Parsing of
+    status reports has been improved. The status query mechanism can be disabled
+    using the -q option. An exit status of 1 implies a system error (eg. can't
+    open the line) while 2 usually means there was an error in the PostScript
+    file. By default postio runs as a single process. The -B, -R, and -q options
+    can be used to speed things up some. A version of the program (previously
+    supplied in postio.tmp) that can help if you seem to be having flow control
+    problems can be obtained using the -S option. It's not generally recommended
+    and should only be used as a last resort!
+
+ 2: Several widthshow encoding schemes have been added to dpost and can reduce
+    print time by 20% or more. The method used to encode lines of text can be
+    changed on the command line using the -e option. Level 0 produces output
+    essentially identical to previous versions of dpost. The default can be
+    changed by modifying the definition of ENCODING in ./Makefile. At present
+    only level 0 is thoroughly tested, although level 2 (ie. -e2) may be the
+    default and is undoubtedly worth a try.
+
+ 3: dpost now supports color selection and reverse video. Access in troff is via
+    the stand-alone macro package ./macros/color. Examples are,
+
+	.so /usr/lib/macros/color
+	.CL red "this prints in red"
+	.CL "white on black" "and this prints white text on a black background"
+
+    The postscript procedures that handle color and reverse video can be found
+    in ./postscript/color.ps. Additional colors can be added to the colordict
+    dictionary defined in ./postscript/color.ps.
+
+ 4: The dpost drawing routines have been improved and have been moved from the
+    prologue (ie. ./postscript/dpost.ps) to ./postscript/draw.ps. That file is
+    only included if needed. Drawing routines now support the ability to group
+    a series of drawing commands together as a single path. May be useful for
+    future versions of pic that wish to fill regions with colors or gray levels.
+    Access is via the new "x X BeginPath" and "x X DrawPath" device control
+    commands. In addition there's some complicated PostScript code in file
+    ./postscript/baseline.ps, that can be used to set text along an arbitrary
+    curve. It's terribly confusing and I doubt anyone will have the patience to
+    bother to figure it out.
+
+ 5: A simple picture packing troff preprocessor (picpack) has been included and
+    the code needed to recover pictures and text has been added to dpost. The
+    program is designed to supplement to the original picture inclusion mechanism,
+    and should ONLY be used when absolutely necessary. Using dpost to pull picture
+    files into a document is strongly recommended and will always be the more
+    efficient and portable approach. picpack simply provides a way to combine
+    pictures and text in a single file before dpost is executed. It may help in
+    a distributed printing environment where the user runs everything through
+    troff while a spooling daemon (eg. lp) handles the postprocessing. There
+    are serious disadvantages to this approach, with perhaps the most important
+    being that troff output files (when picpack is used) will likely result in
+    files that can no longer be reliably passed through other important post-
+    processors like proof.
+
+ 6: Code to handle host resident PostScript fonts in dpost has been tested and
+    finally works. The -H option points dpost to a host resident font directory,
+    which by default is NULL. Host resident font files stored in that directory
+    must be assigned a name that corresponds to the one or two character troff
+    font name. Width tables must also be built (see buildtables/README), the new
+    binary font files must be installed in /usr/lib/font/devpost, and a mapping
+    definition from troff's name to the PostScript font name must be added to
+    ./postscript/dpost.ps.
+
+ 7: The default pattern length in postdmd has been reduced to from 10 to 6 bytes.
+    Printers with fast processors (eg. PS-810s) often benefit from a further
+    reduction, while optimal performance on slower printers (eg PS-800s) may
+    require larger pattern sizes. The pattern length can be set using the -b
+    option. Increasing the pattern size usually increases the size of the output
+    file.
+
+ 8: Line drawing in posttek and postbgi includes code that automatically ties
+    lines to device space coordinates when you select a non-zero width. Helps
+    eliminate the variation in line thickness that many observed. The default
+    line width in posttek and postbgi is still 0 (which gets 1 pixel). If you
+    want a different default change the definition of variable linewidth in files
+    ./postscript/posttek.ps and ./postscript/postbgi.ps.
+
+ 9: Defocused lines in posttek have been fixed.
+
+10: postbgi now supports color and can be used to translate most PRISM (color
+    BGI) jobs. Special device specific tuning needed for many PRISM jobs can be
+    enabled by using the -P"/prism true" option. Missing pieces (eg. subroutines)
+    needed for translating PRISM jobs, have also been implemented.
+
+11: postreverse can reverse the pages in documents that conform to Adobe's 1.0
+    or 2.0 file structuring conventions, and it works with all the translators in
+    this package. The new version is backwards compatible, but files produced by
+    the new translators should not be passed through old versions of postreverse.
+    The likely result will be no output at all. If you choose to do a partial
+    installation put the new postreverse up first!
+
+12: All translators attempt to conform to Adobe's Version 2.0 file structuring
+    conventions. dpost output falls short, but only in the interest of efficiency.
+    Passing dpost output through postreverse (perhaps with the -r option) produces
+    a minimally conforming PostScript file.
+
+13: All the translators now support three options that pass arbitrary PostScript
+    through to the output file. The -P and -C options add a string and the
+    contents of a file respectively immediately after the prologue. It's assumed
+    whatever is added is legitimate PostScript - there is no checking. In each
+    case the added PostScript code becomes part of the job's global environment.
+
+    The -R option can be used to request special action (eg. manualfeed) on a
+    global or page basis.  The argument should be "request", "request:page", or
+    "request:page:file". If page is given as 0 or omitted the request applies
+    globally. If file is omitted the lookup is in /usr/lib/postscript/ps.requests.
+    The collection of recognized requests can be modified or extended by changing
+    /usr/lib/postscript/ps.requests.
+
+14: PostScript code (from Johnathan Shopiro) that produces bolder versions of the
+    Courier fonts has been included in file postscript/fatcourier.ps. The file
+    can  be added to individual prologue files (eg. dpost.ps) or pulled in as
+    needed using the -C option.
+
+15: postmd is a new program that can be used to display a large matrix as a gray
+    scale image. May help if you're looking for patterns in a large matrix. A very
+    optimistic estimate suggests you can display up to a 600x600 matrix (with five
+    different shades of gray) on 300dpi printer using 8.5x11 inch paper.
+
+16: What's available in buildtables has been cleaned up and works well with the
+    new version of postio. It can be used to have PostScript printers build troff
+    width tables for both printer and host resident fonts.
+
+17: The PostScript bind operator has been applied to all procedures that are
+    expected to be executed more than once. Redefined save and restore procedures
+    are no longer needed and saverestore.ps is not included in this package.
+
+18: The bizarre PostScript code used to get to the upper left corner of a page
+    in old versions of dpost.ps and postprint.ps has been replaced by something
+    that's at least slightly more comprehensible. All prologues have also been
+    changed so picture inclusion (eg. including a pic picture that's been run
+    through troff and dpost) should work better than previous versions. Still
+    missing (from most translators) is the %%BoundingBox comment and even when
+    it's put out (by postdmd) only the dimensions are correct - sorry!
+
+19: The careless mistake in the DKHOST section of postio that some noticed belongs
+    to me (not Allan Buckwalter) and has now been fixed.
+
+20: By default all prologues still use the current clipping path to determine page
+    dimensions, but that behavior can be disabled by setting boolean useclippath
+    (in each prologue) to false. In that case the page dimensions will be taken
+    from array pagebbox, which by default is initialized to 8x11 inch paper. The
+    -P options (in each translator) can change useclippth and pagebbox.
+
+21: New in the misc directory is sample lp support from Maryann Csaszar and a
+    simple program that converts host resident font files obtained from a Macintosh
+    to a format that works on Unix.
+
diff --git a/src/cmd/postscript/changes b/src/cmd/postscript/changes
new file mode 100644
index 0000000..500eda2
--- /dev/null
+++ b/src/cmd/postscript/changes
@@ -0,0 +1,95 @@
+add mkfile to each directory for plan9.
+
+common:
+add getopt.c to common.
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in bbox.c.
+comment out strtok(), ftell(), sqrt() atan2() defs in ext.h.
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in misc.c.
+comment out RUNELIB on #endif line in rune.c
+add defined(plan9) in tempnam.c.
+change path.h for plan9!
+
+cropmarks:
+add cropmarks.rc to cropmarks.
+
+download:
+move #include <sys/types.h> before #include <fcntl.h> for off_t in download.c.
+
+dpost:
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in dpost.c.
+added 
+	#ifdef plan9
+	#define	isascii(c)	((unsigned char)(c)<=0177)
+	#endif
+after #include <ctype.h> in dpost.c.
+
+grabit:
+add grabit.rc to grabit.
+
+hardcopy:
+add hardcopy.rc to hardcopy.
+
+postbgi:
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in postbgi.c.
+added 
+	#ifdef plan9
+	#define	isascii(c)	((unsigned char)(c)<=0177)
+	#endif
+after #include <ctype.h> in postbgi.c.
+
+postdaisy:
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in postdaisy.c.
+added 
+	#ifdef plan9
+	#define	isascii(c)	((unsigned char)(c)<=0177)
+	#endif
+after #include <ctype.h> in postdaisy.c.
+
+postdmd:
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in postdmd.c.
+added 
+	#ifdef plan9
+	#define	isascii(c)	((unsigned char)(c)<=0177)
+	#endif
+after #include <ctype.h> in postdmd.c.
+
+postgif:
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in postgif.c.
+added 
+	#ifdef plan9
+	#define	isascii(c)	((unsigned char)(c)<=0177)
+	#endif
+after #include <ctype.h> in postgif.c.
+
+download:
+added #include <string.h> in download.c.
+
+dpost:
+added #include <string.h> in draw.c.
+
+picpack:
+added #include <string.h> in picpack.c.
+
+postmd:
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in postmd.c.
+added 
+	#ifdef plan9
+	#define	isascii(c)	((unsigned char)(c)<=0177)
+	#endif
+after #include <ctype.h> in postmd.c.
+added #include <string.h> in picpack.c.
+
+postprint:
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in postprint.c.
+added 
+	#ifdef plan9
+	#define	isascii(c)	((unsigned char)(c)<=0177)
+	#endif
+after #include <ctype.h> in postprint.c.
+
+postreverse:
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in postreverse.c.
+
+posttek:
+insert #include <sys/types.h> before #include <fcntl.h> for off_t in posttek.c.
+
diff --git a/src/cmd/postscript/common/bbox.c b/src/cmd/postscript/common/bbox.c
index 7e1f14a..66a114c 100644
--- a/src/cmd/postscript/common/bbox.c
+++ b/src/cmd/postscript/common/bbox.c
@@ -34,6 +34,7 @@
 
 /*****************************************************************************/
 
+void
 cover(x, y)
 
     double	x, y;
@@ -65,7 +66,9 @@
 }   /* End of cover */
 
 /*****************************************************************************/
+void	resetbbox();
 
+void
 writebbox(fp, keyword, slop)
 
     FILE	*fp;			/* the comment is written here */
@@ -117,7 +120,7 @@
 }   /* End of writebbox */
 
 /*****************************************************************************/
-
+void
 resetbbox(output)
 
     int		output;
@@ -146,7 +149,7 @@
 }   /* End of resetbbox */
 
 /*****************************************************************************/
-
+void
 scale(sx, sy)
 
     double	sx, sy;
@@ -171,7 +174,7 @@
 }   /* End of scale */
 
 /*****************************************************************************/
-
+void
 translate(tx, ty)
 
     double	tx, ty;
@@ -196,7 +199,7 @@
 }   /* End of translate */
 
 /*****************************************************************************/
-
+void
 rotate(angle)
 
     double	angle;
@@ -223,6 +226,7 @@
 
 /*****************************************************************************/
 
+void
 concat(m1)
 
     double	m1[];
diff --git a/src/cmd/postscript/common/common.c b/src/cmd/postscript/common/common.c
index 945ef6a..a58167a 100644
--- a/src/cmd/postscript/common/common.c
+++ b/src/cmd/postscript/common/common.c
@@ -209,14 +209,14 @@
 int
 cat(char *filename) {
 	Biobuf *bfile;
-	Biobuf *Bfile;
+	Biobufhdr *Bfile;
 	int n;
 	static char buf[Bsize];
 
-	if ((bfile = Bopen(unsharp(filename), OREAD)) == 0) {
+	if ((bfile = Bopen(filename, OREAD)) == 0) {
 		return(1);
 	}
-	Bfile = bfile;
+	Bfile = bfile; /* &(bfile->Biobufhdr); */
 	while ((n=Bread(Bfile, buf, Bsize)) > 0) {
 		if (Bwrite(Bstdout, buf, n) != n)
 			break;
@@ -240,9 +240,9 @@
 }
 
 static char *errorstrings[] = {
-	{""},	/* NONE */
-	{"WARNING"},
-	{"FATAL"}
+	"",	/* NONE */
+	"WARNING",
+	"FATAL"
 };
 
 char *programname;
diff --git a/src/cmd/postscript/common/common.h b/src/cmd/postscript/common/common.h
index 62eba08..2432fe1 100644
--- a/src/cmd/postscript/common/common.h
+++ b/src/cmd/postscript/common/common.h
@@ -5,6 +5,8 @@
 #define	RUNEGETGROUP(a)	((a>>8)&0xff)
 #define	RUNEGETCHAR(a)	(a&0xff)
 
+#define tempnam safe_tempnam
+
 typedef	int	BOOLEAN;
 
 #define	TRUE	1
@@ -38,6 +40,6 @@
 void startpage(void);
 void endpage(void);
 int cat(char *);
-int Bgetfield(Biobuf *, int, void *, int);
+int Bgetfield(Biobufhdr *, int, void *, int);
 void *galloc(void *, int, char *);
 void pagelist(char *);
diff --git a/src/cmd/postscript/common/ext.h b/src/cmd/postscript/common/ext.h
index e260cee..c0f7c7a 100644
--- a/src/cmd/postscript/common/ext.h
+++ b/src/cmd/postscript/common/ext.h
@@ -28,8 +28,12 @@
 extern int	optind;
 
 extern void	interrupt();
-//extern char	*tempnam(char*,char*);
+extern void	error();
+extern int	cat();
+extern void	concat();
+
 /* 
+ * extern char	*tempnam(char*,char*);
  * extern char	*malloc();
  * extern char	*calloc();
  * extern char	*strtok();
diff --git a/src/cmd/postscript/common/gen.h b/src/cmd/postscript/common/gen.h
index ba8cbba..dffeb95 100644
--- a/src/cmd/postscript/common/gen.h
+++ b/src/cmd/postscript/common/gen.h
@@ -7,6 +7,10 @@
 
 #define PROGRAMVERSION	"3.3.2"
 
+/* XXX: replace tempnam with something safer, but leaky */
+extern	char*	safe_tempnam(char*, char*);
+#define	tempnam	safe_tempnam
+
 #define NON_FATAL	0
 #define FATAL		1
 #define USER_FATAL	2
diff --git a/src/cmd/postscript/common/getopt.c b/src/cmd/postscript/common/getopt.c
index cf6619f..e348cb2 100644
--- a/src/cmd/postscript/common/getopt.c
+++ b/src/cmd/postscript/common/getopt.c
@@ -15,7 +15,7 @@
 char **argv, *opts;
 {
 	static int sp = 1;
-	register c;
+	register int c;
 	register char *cp;
 
 	if (sp == 1)
diff --git a/src/cmd/postscript/common/misc.c b/src/cmd/postscript/common/misc.c
index 25bd37a..198a935 100644
--- a/src/cmd/postscript/common/misc.c
+++ b/src/cmd/postscript/common/misc.c
@@ -8,6 +8,8 @@
 #include <ctype.h>
 #include <sys/types.h>
 #include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
 
 #include "gen.h"
 #include "ext.h"
@@ -17,7 +19,9 @@
 int	olist[50];			/* processing range pairs */
 
 /*****************************************************************************/
+extern	int	str_convert();
 
+void
 out_list(str)
 
     char	*str;
@@ -53,7 +57,7 @@
 }   /* End of out_list */
 
 /*****************************************************************************/
-
+int
 in_olist(num)
 
     int		num;
@@ -80,7 +84,7 @@
 }   /* End of in_olist */
 
 /*****************************************************************************/
-
+void
 setencoding(name)
 
     char	*name;
@@ -110,7 +114,7 @@
 }   /* End of setencoding */
 
 /*****************************************************************************/
-
+int
 cat(file)
 
     char	*file;
@@ -145,6 +149,7 @@
 
 /*****************************************************************************/
 
+int
 str_convert(str, err)
 
     char	**str;
@@ -173,6 +178,7 @@
 
 /*****************************************************************************/
 
+void
 error(kind, mesg, a1, a2, a3)
 
     int		kind;
@@ -191,9 +197,9 @@
 	fprintf(stderr, "%s: ", prog_name);
 	fprintf(stderr, mesg, a1, a2, a3);
 	if ( lineno > 0 )
-	    fprintf(stderr, " (line %d)", lineno);
+	    fprintf(stderr, " (line %ld)", lineno);
 	if ( position > 0 )
-	    fprintf(stderr, " (near byte %d)", position);
+	    fprintf(stderr, " (near byte %ld)", position);
 	putc('\n', stderr);
     }	/* End if */
 
diff --git a/src/cmd/postscript/common/path.h b/src/cmd/postscript/common/path.h
index a369213..68f8cbf 100644
--- a/src/cmd/postscript/common/path.h
+++ b/src/cmd/postscript/common/path.h
@@ -4,29 +4,29 @@
  *
  */
 
-#define DPOST		"#9/sys/lib/postscript/prologues/dpost.ps"
-#define POSTBGI		"#9/sys/lib/postscript/prologues/postbgi.ps"
-#define POSTDAISY	"#9/sys/lib/postscript/prologues/postdaisy.ps"
-#define POSTDMD		"#9/sys/lib/postscript/prologues/postdmd.ps"
-#define POSTMD		"#9/sys/lib/postscript/prologues/postmd.ps"
-#define POSTPLOT	"#9/sys/lib/postscript/prologues/postplot.ps"
-#define POSTPRINT	"#9/sys/lib/postscript/prologues/postprint.ps"
-#define POSTNPRINT	"#9/sys/lib/postscript/prologues/postnprint.ps"
-#define POSTTEK		"#9/sys/lib/postscript/prologues/posttek.ps"
-#define POSTGIF		"#9/sys/lib/postscript/prologues/postgif.ps"
+#define DPOST		"#9/postscript/prologues/dpost.ps"
+#define POSTBGI		"#9/postscript/prologues/postbgi.ps"
+#define POSTDAISY	"#9/postscript/prologues/postdaisy.ps"
+#define POSTDMD		"#9/postscript/prologues/postdmd.ps"
+#define POSTMD		"#9/postscript/prologues/postmd.ps"
+#define POSTPLOT	"#9/postscript/prologues/postplot.ps"
+#define POSTPRINT	"#9/postscript/prologues/postprint.ps"
+#define POSTNPRINT	"#9/postscript/prologues/postnprint.ps"
+#define POSTTEK		"#9/postscript/prologues/posttek.ps"
+#define POSTGIF		"#9/postscript/prologues/postgif.ps"
 
-#define BASELINE	"#9/sys/lib/postscript/prologues/baseline.ps"
-#define COLOR		"#9/sys/lib/postscript/prologues/color.ps"
-#define DRAW		"#9/sys/lib/postscript/prologues/draw.ps"
-#define FORMFILE	"#9/sys/lib/postscript/prologues/forms.ps"
-#define SHADEFILE	"#9/sys/lib/postscript/prologues/shade.ps"
-#define KERNING		"#9/sys/lib/postscript/prologues/kerning.ps"
-#define REQUESTFILE	"#9/sys/lib/postscript/prologues/ps.requests"
-#define ROUNDPAGE	"#9/sys/lib/postscript/prologues/roundpage.ps"
+#define BASELINE	"#9/postscript/prologues/baseline.ps"
+#define COLOR		"#9/postscript/prologues/color.ps"
+#define DRAW		"#9/postscript/prologues/draw.ps"
+#define FORMFILE	"#9/postscript/prologues/forms.ps"
+#define SHADEFILE	"#9/postscript/prologues/shade.ps"
+#define KERNING		"#9/postscript/prologues/kerning.ps"
+#define REQUESTFILE	"#9/postscript/prologues/ps.requests"
+#define ROUNDPAGE	"#9/postscript/prologues/roundpage.ps"
 
-#define ENCODINGDIR	"#9/sys/lib/postscript/prologues"
-#define HOSTDIR		"#9/sys/lib/postscript/font"
-#define FONTDIR		"#9/sys/lib/troff/font"
-#define POSTLIBDIR	"#9/sys/lib/postscript/prologues"
-#define TEMPDIR		"/tmp"
+#define ENCODINGDIR	"#9/postscript/prologues"
+#define HOSTDIR		"#9/postscript/font"
+#define FONTDIR		"#9/troff/font"
+#define POSTLIBDIR	"#9/postscript/prologues"
+#define TEMPDIR		"#9/tmp"
 
diff --git a/src/cmd/postscript/common/request.c b/src/cmd/postscript/common/request.c
index d8d7dd1..7884b23 100644
--- a/src/cmd/postscript/common/request.c
+++ b/src/cmd/postscript/common/request.c
@@ -11,8 +11,12 @@
  */
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 
 #include "gen.h"			/* general purpose definitions */
+#include "ext.h"
 #include "request.h"			/* a few special definitions */
 #include "path.h"			/* for the default request file */
 
@@ -22,6 +26,7 @@
 
 /*****************************************************************************/
 
+void
 saverequest(want)
 
     char	*want;			/* grab code for this stuff */
@@ -55,7 +60,9 @@
 }   /* End of saverequest */
 
 /*****************************************************************************/
+extern	void	dumprequest();
 
+void
 writerequest(page, fp_out)
 
     int		page;			/* write everything for this page */
@@ -80,6 +87,7 @@
 
 /*****************************************************************************/
 
+void
 dumprequest(want, file, fp_out)
 
     char	*want;			/* look for this string */
diff --git a/src/cmd/postscript/common/tempnam.c b/src/cmd/postscript/common/tempnam.c
index 529025e..a759876 100644
--- a/src/cmd/postscript/common/tempnam.c
+++ b/src/cmd/postscript/common/tempnam.c
@@ -1,27 +1,62 @@
 #include <stdio.h>
-#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 
-#if defined(V9) || defined(BSD4_2) || defined(plan9)
-char *tempnam(char *dir, char *pfx) {
-	int pid;
-	unsigned int len;
-	char *tnm, *malloc();
-	static int seq = 0;
+#define nil ((void*)0)
 
-	pid = getpid();
-	len = strlen(dir) + strlen(pfx) + 10;
-	if ((tnm = malloc(len)) != NULL) {
-		sprintf(tnm, "%s", dir);
-		if (access(tnm, 7) == -1)
-			return(NULL);
-		do {
-			sprintf(tnm, "%s/%s%d%d", dir, pfx, pid, seq++);
-			errno = 0;
-			if (access(tnm, 7) == -1)
-				if (errno == ENOENT)
-					return(tnm);
-		} while (1);
-	}
-	return(tnm);
+char*
+mkfname(char *tmpdir, char *prefix)
+{
+	int n;
+	char *p, *fname;
+
+	if((p = getenv("TMPDIR")) != nil)
+		goto Mktemp;
+	if((p = tmpdir) != nil)
+		goto Mktemp;
+	p = "/tmp";
+
+ Mktemp:
+	n = strlen(p)+1+strlen(prefix)+1+8+1;
+	if((fname = malloc(n)) == nil)
+		return nil;
+	memset(fname, 0, n);
+	strcat(fname, p);
+	if((n = strlen(p)) > 0 && p[n-1] != '/')
+		strcat(fname, "/");
+	strcat(fname, prefix);
+	strcat(fname, ".XXXXXXXX");
+
+	return fname;
 }
-#endif
+
+extern int mkstemp();
+
+char*
+safe_tempnam(char *tmpdir, char *prefix)
+{
+	int fd;
+	char *fname;
+
+	if((fname = mkfname(tmpdir, prefix)) == nil)
+		return nil;
+
+	if((fd = mkstemp(fname)) < 0){		/* XXX: leak fd, fname */
+		free(fname);
+		return nil;
+	}
+	return fname;
+}
+
+int
+safe_tmpnam(char *fname)
+{
+	char *p;
+
+	if((p = mkfname(nil, "tmpfile")) == nil)
+		return -1;
+	strcpy(fname, p);
+	free(p);
+	return mkstemp(fname);
+}
diff --git a/src/cmd/postscript/config b/src/cmd/postscript/config
new file mode 100644
index 0000000..fa9bb27
--- /dev/null
+++ b/src/cmd/postscript/config
@@ -0,0 +1,12 @@
+# edit ../ps.mk instead
+SYSTEM=plan9
+VERSION=3.3.1
+
+ROOT=
+POSTBIN=$ROOT/$objtype/bin/aux
+DKHOST=FALSE
+DKSTREAMS=FALSE
+ROUNDPAGE=TRUE
+
+FONTDIR=/sys/lib/troff/font
+POSTLIB=/sys/lib/postscript/prologues
diff --git a/src/cmd/postscript/download/download.c b/src/cmd/postscript/download/download.c
index ab6bdd5..5a6bdf3 100644
--- a/src/cmd/postscript/download/download.c
+++ b/src/cmd/postscript/download/download.c
@@ -99,10 +99,10 @@
  *
  */
 
-    fp_in = stdin;
-
     argc = agc;				/* other routines may want them */
     argv = agv;
+    
+    fp_in = stdin;
 
     prog_name = argv[0];		/* just for error messages */
 
@@ -244,7 +244,7 @@
 	sprintf(path, "%s/%s%s", hostfontdir, mapname, suffix);
     } else path = mapname;
 
-    if ( (fd = open(unsharp(path), 0)) != -1 ) {
+    if ( (fd = open(path, 0)) != -1 ) {
 	if ( fstat(fd, &sbuf) == -1 )
 	    error(FATAL, "can't fstat %s", path);
 	if ( (stringspace = (char *)malloc(sbuf.st_size + 2)) == NULL )
@@ -303,7 +303,7 @@
 	path = buf;
     } else path = residentfonts;
 
-    if ( (fp = fopen(unsharp(path), "r")) != NULL ) {
+    if ( (fp = fopen(path, "r")) != NULL ) {
 	while ( fscanf(fp, "%s", buf) != EOF )
 	    if ( buf[0] == '%' )
 		while ( (ch = getc(fp)) != EOF && ch != '\n' ) ;
@@ -336,7 +336,7 @@
 	    fp_temp = NULL;
 	    if ( strcmp(*argv, "-") == 0 )
 		fp_in = stdin;
-	    else if ( (fp_in = fopen(unsharp(*argv), "r")) == NULL )
+	    else if ( (fp_in = fopen(*argv, "r")) == NULL )
 		error(FATAL, "can't open %s", *argv);
 	    download();
 	    if ( fp_in != stdin )
@@ -449,9 +449,9 @@
 		if ( (path = (char *)malloc(strlen(hostfontdir)+strlen(map[n].file)+2)) == NULL )
 		    error(FATAL, "no memory");
 		sprintf(path, "%s/%s", hostfontdir, map[n].file);
-		cat(unsharp(path));
+		cat(path);
 		free(path);
-	    } else cat(unsharp(map[n].file));
+	    } else cat(map[n].file);
 	    map[n].downloaded = TRUE;
 	}   /* End if */
     }	/* End while */
diff --git a/src/cmd/postscript/hardcopy/README b/src/cmd/postscript/hardcopy/README
new file mode 100644
index 0000000..2ad2906
--- /dev/null
+++ b/src/cmd/postscript/hardcopy/README
@@ -0,0 +1,11 @@
+Redirect output of the print operator to paper. Particularly useful if
+you're trying to extract information from a printer, but you don't have
+access to the data the printer returns to the host.
+
+For example,
+
+	FontDirectory {pop ==} forall
+
+names all the fonts registered in the FontDirectory dictionary. Simple,
+but only if you can read the data returned to the host by the printer.
+
diff --git a/src/cmd/postscript/hardcopy/hardcopy.ps b/src/cmd/postscript/hardcopy/hardcopy.ps
new file mode 100644
index 0000000..65eb24d
--- /dev/null
+++ b/src/cmd/postscript/hardcopy/hardcopy.ps
@@ -0,0 +1,196 @@
+%
+% Redefiniton of the PostScript file output operators so results go to paper.
+% Complicated and slow, but the implementation doesn't place many demands on
+% included PostScript. About all that's required is gentle treatment of the
+% graphics state between write calls.
+%
+
+/#copies 1 store
+/aspectratio 1 def
+/font /Courier def
+/formsperpage 1 def
+/landscape false def
+/magnification 1 def
+/orientation 0 def
+/pointsize 10 def
+/rotation 1 def
+/xoffset .1 def
+/yoffset .1 def
+
+/roundpage true def
+/useclippath true def
+/pagebbox [0 0 612 792] def
+
+/inch {72 mul} def
+/min {2 copy gt {exch} if pop} def
+
+/HardcopySetup {
+	landscape {/orientation 90 orientation add def} if
+	font findfont 1 1.1 div scalefont setfont
+
+	pagedimensions
+	xcenter ycenter translate
+	orientation rotation mul rotate
+	width 2 div neg height 2 div translate
+	xoffset inch yoffset inch neg translate
+	pointsize 1.1 mul dup scale
+	magnification dup aspectratio mul scale
+	height width div 1 min dup scale
+	0 -1 translate
+	0 0 moveto
+} def
+
+/pagedimensions {
+	useclippath {
+		/pagebbox [clippath pathbbox newpath] def
+		roundpage currentdict /roundpagebbox known and {roundpagebbox} if
+	} if
+	pagebbox aload pop
+	4 -1 roll exch 4 1 roll 4 copy
+	landscape {4 2 roll} if
+	sub /width exch def
+	sub /height exch def
+	add 2 div /xcenter exch def
+	add 2 div /ycenter exch def
+} def
+
+%
+% Unbind the operators in an executable array or packedarray. Leaves the
+% unbound array or the original object on the stack.
+%
+
+/Unbind {
+	0 index xcheck
+	1 index type /arraytype eq
+	2 index type /packedarraytype eq or and {
+		dup length array copy cvx
+		dup 0 exch {
+			dup type /operatortype eq {
+				(                          ) cvs cvn cvx
+			} if
+
+			dup type /dicttype eq {
+				dup maxlength dict exch {
+					Unbind
+					3 copy put pop pop
+				} forall
+			} if
+
+			0 index xcheck
+			1 index type /arraytype eq
+			2 index type /packedarraytype eq or and {
+				Unbind
+			} if
+
+			3 copy put pop
+			1 add
+		} forall
+		pop
+	} if
+} def
+
+%
+% New write operator - don't bind the definition! Expands tabs and backspaces,
+% wraps long lines, and starts a new page whenever necessary. The code that
+% handles newlines assumes lines are separated by one vertical unit.
+%
+
+/write {
+	true exch
+
+      %%case '\b':
+	dup 8#10 eq {
+		( ) stringwidth pop neg 0 rmoveto
+		currentpoint pop 0 lt {
+			currentpoint exch pop 0 exch moveto
+		} if
+		exch pop false exch
+	} if
+
+      %%case '\t':
+	dup 8#11 eq {
+		currentpoint pop ( ) stringwidth pop div round cvi
+		8 mod 8 exch sub {
+			2 index 8#40 write
+		} repeat
+		exch pop false exch
+	} if
+
+      %%case '\n':
+	dup 8#12 eq {
+		currentpoint 0 exch 1 sub moveto pop
+
+		gsave clippath pathbbox pop pop exch pop grestore
+		currentpoint exch pop 1 sub ge {
+			2 index 8#14 write
+		} if
+		exch pop false exch
+	} if
+
+      %%case '\f':
+	dup 8#14 eq {
+		gsave showpage grestore
+		0 0 moveto
+		exch pop false exch
+	} if
+
+      %%case '\r':
+	dup 8#15 eq {
+		currentpoint 0 exch moveto pop
+		exch pop false exch
+	} if
+
+      %%case EOF:
+	dup -1 eq {
+		currentpoint 0 ne exch 0 ne or {
+			2 index 8#14 write
+		} if
+		exch pop false exch
+	} if
+
+      %%default:
+	exch {
+		dup
+		gsave clippath pathbbox pop 3 1 roll pop pop grestore 
+		( ) stringwidth pop currentpoint pop add le {
+			2 index 8#12 write
+		} if
+		( ) dup 0 4 -1 roll put show
+	} if
+
+	pop		% the character
+	pop		% and file object
+} def
+
+%
+% All the other file output operators call our redefined write operator.
+%
+
+/print {
+	(%stdout) (w) file exch {1 index exch write} forall
+	pop
+} def
+
+/writestring {
+	{1 index exch write} forall
+	pop
+} def
+
+/writehexstring {
+	(0123456789ABCDEF) 3 1 roll {
+		dup
+		3 index exch -4 bitshift 16#F and get 2 index exch write
+		2 index exch 16#F and get 1 index exch write
+	} forall
+	pop pop
+} def
+
+%
+% Unbind and redefine the remaining file output procedures.
+%
+
+/= dup load Unbind def
+/== dup load Unbind def
+/stack dup load Unbind def
+/pstack dup load Unbind def
+
diff --git a/src/cmd/postscript/hardcopy/hardcopy.rc b/src/cmd/postscript/hardcopy/hardcopy.rc
new file mode 100644
index 0000000..0077aa7
--- /dev/null
+++ b/src/cmd/postscript/hardcopy/hardcopy.rc
@@ -0,0 +1,70 @@
+#!/bin/rc
+# Generate paper output from the data that a PostScript program normally
+# sends back to a host computer using file output operators.
+#
+
+POSTLIB=/sys/lib/postscript/prologues
+PROLOGUE=$POSTLIB/hardcopy.ps
+
+OPTIONS=
+MODE=portrait
+
+NONCONFORMING='%!PS'
+ENDPROLOG='%%EndProlog'
+BEGINSETUP='%%BeginSetup'
+ENDSETUP='%%EndSetup'
+TRAILER='%%Trailer'
+
+SETUP=HardcopySetup
+DONE='(%stdout)(w) file -1 write'
+
+while (! ~ $#* 0 && ~ $1 -*) {
+	switch ($1) {
+	case -c;  shift; OPTIONS=$OPTIONS' /#copies '$1' store'
+	case -c*; OPTIONS=$OPTIONS' /#copies `{echo $1 | sed s/-c//}' store'
+
+	case -f;  shift; OPTIONS=$OPTIONS' /font '/$1' def'
+	case -f*; OPTIONS=$OPTIONS' /font '/`{echo $1 | sed s/-f//}' def'
+
+	case -p;  shift; MODE=$1
+	case -p*; MODE=`{echo $1 | sed s/-p//}
+
+	case -m;  shift; OPTIONS=$OPTIONS' /magnification '$1' def'
+	case -m*; OPTIONS=$OPTIONS' /magnification '`{echo $1 | sed s/-m//}' def'
+
+	case -s;  shift; OPTIONS=$OPTIONS' /pointsize '$1' def'
+	case -s*; OPTIONS=$OPTIONS' /pointsize '`{echo $1 | sed s/-s//}' def'
+
+	case -x;  shift; OPTIONS=$OPTIONS' /xoffset '$1' def'
+	case -x*; OPTIONS=$OPTIONS' /xoffset '`{echo $1 | sed s/-x//}' def'
+
+	case -y;  shift; OPTIONS=$OPTIONS' /yoffset '$1' def'
+	case -y*; OPTIONS=$OPTIONS' /yoffset '`{echo $1 | sed s/-y//}' def'
+
+	case -L;  shift; PROLOGUE=$1
+	case -L*; PROLOGUE=`{echo $1 | sed s/-L//}
+
+	case --;
+
+	case -*;  echo '$0: illegal option $1' >&2; exit 1
+	}
+	shift
+}
+
+switch ($MODE) {
+	case l*; OPTIONS=$OPTIONS' /landscape true def'
+	case *;  OPTIONS=$OPTIONS' /landscape false def'
+}
+
+echo $NONCONFORMING
+cat $PROLOGUE
+echo $ENDPROLOG
+echo $BEGINSETUP
+echo $OPTIONS
+echo $SETUP
+echo $ENDSETUP
+
+cat $*
+
+echo $TRAILER
+echo $DONE
diff --git a/src/cmd/postscript/hardcopy/mkfile b/src/cmd/postscript/hardcopy/mkfile
new file mode 100644
index 0000000..c6131db
--- /dev/null
+++ b/src/cmd/postscript/hardcopy/mkfile
@@ -0,0 +1,20 @@
+</$objtype/mkfile
+
+<../config
+
+all:V:	hardcopy
+
+installall install:V:	$POSTBIN/hardcopy $POSTLIB/hardcopy.ps
+
+$POSTBIN/hardcopy:	hardcopy
+	cp $prereq $target
+
+$POSTLIB/hardcopy.ps:	hardcopy.ps
+	cp $prereq $target
+
+hardcopy:	hardcopy.rc
+	sed 's?^POSTLIB=.*?POSTLIB='$POSTLIB'?' hardcopy.rc >hardcopy
+	chmod 775 hardcopy
+
+clean nuke:V:
+	rm -f hardcopy
diff --git a/src/cmd/postscript/mcolor/.cvsignore b/src/cmd/postscript/mcolor/.cvsignore
new file mode 100644
index 0000000..0c5af57
--- /dev/null
+++ b/src/cmd/postscript/mcolor/.cvsignore
@@ -0,0 +1 @@
+tmac.color
diff --git a/src/cmd/postscript/mcolor/color.sr b/src/cmd/postscript/mcolor/color.sr
new file mode 100644
index 0000000..0a63aad
--- /dev/null
+++ b/src/cmd/postscript/mcolor/color.sr
@@ -0,0 +1,45 @@
+.ds Dc black
+.ds Cc \*(Dc
+.de CL	\" Color selection macro
+.	\"
+.	\"	$1=color (e.g. .CL red) or
+.	\"	$1=textcolor on backgroundcolor (e.g. .CL "red on blue")
+.	\"	$1=red green blue rgb (e.g. .CL ".2 .3 .4 rgb") or
+.	\"	$1=hue saturation brightness hsb (e.g. .CL ".5 .6 .7 hsb")
+.	\"	$2=text
+.	\"
+.	\" If no arguments are given the default color (usually black) will be
+.	\" restored. If $2 is omitted the color selected by $1 remains in effect
+.	\" until another color is selected. If two arguments are given $2 will be
+.	\" printed in color $1 and then the default color will be restored.
+.	\"
+.	\" The color of the text and the background can be selected by setting $1
+.	\" to "textcolor on backgroundcolor" where textcolor and backgroundcolor
+.	\" can be any of the known colors. For example use .CL "white on black"
+.	\" for reverse video printing. Changing color in a word can be accomplished
+.	\" by preceeding the characters with a \X'SetColor:val' command, where val
+.	\" is the color you wish to use. Named colors are case independent.
+.	\"
+.	\" Implementation details are device dependent and are handled in the
+.	\" appropriate post-processor. Requesting a color that's not available
+.	\" (eg. not defined in /usr/lib/postscript/color.ps) results in the use
+.	\" of default colors - black or white on black for reverse video mode.
+.	\"
+.	\" All colors may not be supported on every output device, and the direct
+.	\" specification of a color via an explicit rgb or hsb argument may also
+.	\" be device dependent. In any case, to be safe on PostScript devices, all
+.	\" numeric paramenters in the direct rgb or hsb specifications should lie
+.	\" between 0 and 1 (inclusive). The names of the currently available colors
+.	\" on PostScript printers are listed in file /usr/lib/postscript/color.ps.
+.	\"
+.mk Ov
+.if \\n(.$=0 .ds Cc \\*(Dc
+.if \\n(.$=1 .ds Cc \\$1
+.if \\n(.$<2 \\X'SetColor:\\*(Cc'
+.if \\n(.$=2 \\X'SetColor:\\$1'\\c
+.if \\n(.$=2 'sp |\\n(Ovu
+.if \\n(.$=2 \\$2
+.if \\n(.$=2 .mk Ov
+.if \\n(.$=2 \\X'SetColor:\\*(Cc'\\c
+'sp |\\n(Ovu
+..
diff --git a/src/cmd/postscript/mcolor/mcolor.5 b/src/cmd/postscript/mcolor/mcolor.5
new file mode 100644
index 0000000..bf0181f
--- /dev/null
+++ b/src/cmd/postscript/mcolor/mcolor.5
@@ -0,0 +1,60 @@
+.ds dP /usr/lib/postscript
+.ds dT /usr/lib/tmac
+.TH MCOLOR 5
+.SH NAME
+.B mcolor
+\- color and reverse video macro
+.SH SYNOPSIS
+\*(mBtroff \-mcolor\f1
+.OP "" options []
+.OP "" files []
+.SH DESCRIPTION
+.B mcolor
+is a macro package for color selection and reverse video printing
+on PostScript printers.
+The package is compatible with most existing macro packages
+and includes the following macro:
+.TP 1.25i
+.MI .CL "\0color\0text"
+Prints
+.I text
+in
+.IR color .
+No arguments restores the default color (black).
+If
+.I text
+is omitted the selected
+.I color
+remains in effect until another
+.I color
+is selected.
+If two arguments are given the
+.I text
+is printed in
+.I color
+and then the default color is restored.
+.PP
+Both the text and background color can be selected.
+A
+.I color
+argument of
+.RI `` color1
+.MW on
+.IR color2 ''
+prints text in
+.I color1
+on a background in
+.I color2 .
+.PP
+Named colors must be listed in the
+``colordict''
+dictionary in file
+.MR \*(dP/color.ps .
+.SH FILES
+.MW \*(dT/tmac.color
+.br
+.MW \*(dP/color.ps
+.SH SEE ALSO
+.BR troff (1),
+.BR dpost (1),
+.BR mps (5)
diff --git a/src/cmd/postscript/mcolor/mcolor.mk b/src/cmd/postscript/mcolor/mcolor.mk
new file mode 100644
index 0000000..aacadcf
--- /dev/null
+++ b/src/cmd/postscript/mcolor/mcolor.mk
@@ -0,0 +1,53 @@
+#
+# Not installing the man page.
+#
+
+MAKE=/bin/make
+MAKEFILE=mcolor.mk
+
+SYSTEM=V9
+VERSION=3.3.2
+
+OWNER=bin
+GROUP=bin
+
+POSTLIB=/usr/lib/postscript
+TMACDIR=/usr/lib/tmac
+
+all :
+	@cp color.sr tmac.color
+
+install : all
+	@if [ ! -d $(TMACDIR) ]; then \
+	    mkdir $(TMACDIR); \
+	    chmod 755 $(TMACDIR); \
+	    chgrp $(GROUP) $(TMACDIR); \
+	    chown $(OWNER) $(TMACDIR); \
+	fi
+	cp tmac.color $(TMACDIR)/tmac.color
+	@chmod 644 $(TMACDIR)/tmac.color
+	@chgrp $(GROUP) $(TMACDIR)/tmac.color
+	@chown $(OWNER) $(TMACDIR)/tmac.color
+
+clean :
+	rm -f tmac.color
+
+clobber : clean
+
+changes :
+	@trap "" 1 2 3 15; \
+	sed \
+	    -e "s'^SYSTEM=.*'SYSTEM=$(SYSTEM)'" \
+	    -e "s'^VERSION=.*'VERSION=$(VERSION)'" \
+	    -e "s'^GROUP=.*'GROUP=$(GROUP)'" \
+	    -e "s'^OWNER=.*'OWNER=$(OWNER)'" \
+	    -e "s'^POSTLIB=.*'POSTLIB=$(POSTLIB)'" \
+	    -e "s'^TMACDIR=.*'TMACDIR=$(TMACDIR)'" \
+	$(MAKEFILE) >X$(MAKEFILE); \
+	mv X$(MAKEFILE) $(MAKEFILE); \
+	sed \
+	    -e "s'^.ds dP.*'.ds dP $(POSTLIB)'" \
+	    -e "s'^.ds dT.*'.ds dT $(TMACDIR)'" \
+	mcolor.5 >Xmcolor.5; \
+	mv Xmcolor.5 mcolor.5
+
diff --git a/src/cmd/postscript/misc/.cvsignore b/src/cmd/postscript/misc/.cvsignore
new file mode 100644
index 0000000..c865cf4
--- /dev/null
+++ b/src/cmd/postscript/misc/.cvsignore
@@ -0,0 +1,4 @@
+ibmfont
+laserbar
+macfont
+pscrypt
diff --git a/src/cmd/postscript/misc/README b/src/cmd/postscript/misc/README
new file mode 100644
index 0000000..d17f15d
--- /dev/null
+++ b/src/cmd/postscript/misc/README
@@ -0,0 +1,15 @@
+Miscellaneous programs - all are unsupported.
+
+  ibmfont.c	IBM PC to Unix font conversion program
+  laserbar.[c1]	Barcode filter and man page - Jan Wolitzky
+  lp.model	Sample lp interface (not for Unix 4.0) - Maryann Csaszar
+  macfont.c	Macintosh to Unix font conversion program
+  pscrypt.c	Quick implementation of Adobe's encryption/decryption algorithm
+  setbaud.ps	Example of how to change the printer's baudrate
+
+Use make to compile C programs. For example,
+
+	make macfont
+
+compiles macfont.c.
+
diff --git a/src/cmd/postscript/misc/ibmfont.c b/src/cmd/postscript/misc/ibmfont.c
new file mode 100644
index 0000000..49736d6
--- /dev/null
+++ b/src/cmd/postscript/misc/ibmfont.c
@@ -0,0 +1,296 @@
+/*
+ *
+ * Program that converts IBM font files to a format that works on Unix systems.
+ * Essentially all the information needed came from the Adobe paper "Supporting
+ * Downloadable PostScript Fonts". To use the program type,
+ *
+ *	ibmfont font.ibm >font.unix
+ *
+ * where font.ibm is the font file, exactly as it came over from an IBM PC,
+ * and font.unix is equivalent host resident font file usable on Unix systems.
+ * 
+ */
+
+#include <stdio.h>
+#include <signal.h>
+
+#define OFF		0
+#define ON		1
+
+#define NON_FATAL	0
+#define FATAL		1
+
+#define FALSE		0
+#define TRUE		1
+
+char	**argv;
+int	argc;
+
+char	*prog_name;
+
+int	x_stat;
+int	debug = OFF;
+int	ignore = OFF;
+
+FILE	*fp_in;
+FILE	*fp_out;
+
+/*****************************************************************************/
+
+main(agc, agv)
+
+    int		agc;
+    char	*agv[];
+
+{
+
+/*
+ *
+ * IBM PC to Unix font converter.
+ *
+ */
+
+    argc = agc;
+    argv = agv;
+    prog_name = argv[0];
+
+    fp_in = stdin;
+    fp_out = stdout;
+
+    options();
+    arguments();
+    exit(x_stat);
+
+}   /* End of main */
+
+/*****************************************************************************/
+
+options()
+
+{
+
+    int		ch;
+    char	*names = "DI";
+
+    extern char	*optarg;
+    extern int	optind;
+
+/*
+ *
+ * Command line options.
+ *
+ */
+
+    while ( (ch = getopt(argc, argv, names)) != EOF ) {
+	switch ( ch ) {
+	    case 'D':			/* debug flag */
+		    debug = ON;
+		    break;
+
+	    case 'I':			/* ignore FATAL errors */
+		    ignore = ON;
+		    break;
+
+	    case '?':			/* don't understand the option */
+		    error(FATAL, "");
+		    break;
+
+	    default:			/* don't know what to do for ch */
+		    error(FATAL, "missing case for option %c\n", ch);
+		    break;
+	}   /* End switch */
+    }   /* End while */
+
+    argc -= optind;
+    argv += optind;
+
+}   /* End of options */
+
+/*****************************************************************************/
+
+arguments()
+
+{
+
+/*
+ *
+ * Everything esle is an input file. No arguments or '-' means stdin.
+ *
+ */
+
+
+    if ( argc < 1 )
+	conv();
+    else
+	while ( argc > 0 ) {
+	    if ( strcmp(*argv, "-") == 0 )
+		fp_in = stdin;
+	    else if ( (fp_in = fopen(*argv, "r")) == NULL )
+		error(FATAL, "can't open %s", *argv);
+	    conv();
+	    if ( fp_in != stdin )
+		fclose(fp_in);
+	    argc--;
+	    argv++;
+	}   /* End while */
+
+}   /* End of arguments */
+
+/*****************************************************************************/
+
+conv()
+
+{
+
+    int		blocksize;
+    int		blocktype;
+    int		seg;
+    long	ftell();
+
+/*
+ *
+ * Font files on the IBM PC are stored in a compressed binary format. Individual
+ * segments in the file are preceeded by a header that looks like,
+ *
+ *		Byte 1:		128
+ *		Byte 2:		segment type (1=ASCII, 2=TOHEX, or 3=EOF)
+ *		Bytes 3-6:	length of the segment
+ *		Bytes 7 ...	data
+ *
+ */
+
+    while ( 1 ) {
+	seg = ftell(fp_in);
+	if ( getc(fp_in) != 128 )
+	    error(FATAL, "bad file format");
+	blocktype = getc(fp_in);
+	blocksize = getint(fp_in);
+	if ( debug == ON ) {
+	    fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize);
+	    fprintf(stderr, "start=0%o, end=0%o\n", seg, seg+blocksize+6);
+	    fprintf(stderr, "start=%d, end=%d\n", seg, seg+blocksize+6);
+	}   /* End if */
+	switch ( blocktype ) {
+	    case 1:
+		asciitext(blocksize);
+		break;
+
+	    case 2:
+		hexdata(blocksize);
+		break;
+
+	    case 3:
+		return;
+
+	    default:
+		error(FATAL, "unknown resource type %d", blocktype);
+	}   /* End switch */
+    }	/* End while */
+
+}   /* End of conv */
+
+/*****************************************************************************/
+
+asciitext(count)
+
+    int		count;			/* bytes left in the block */
+
+{
+
+    int		ch;
+    int		i = 0;
+
+/*
+ *
+ * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines
+ * is all I've done.
+ *
+ */
+
+    for ( i = 0; i < count; i++ ) {
+	if ( (ch = getc(fp_in)) == '\r' )
+	    ch = '\n';
+	putc(ch, fp_out);
+    }	/* End for */
+	
+}   /* End of asciitext */
+
+/*****************************************************************************/
+
+hexdata(count)
+
+    int		count;			/* bytes left in the block */
+
+{
+
+    int		i;
+    int		n;
+
+/*
+ *
+ * Reads the next count bytes and converts each byte to hex. Also starts a new
+ * line every 80 hex characters.
+ *
+ */
+
+    for ( i = 0, n = 0; i < count; i++ ) {
+	fprintf(fp_out, "%.2X", getc(fp_in));
+	if ( (++n % 40) == 0 )
+	    putc('\n', fp_out);
+    }	/* End for */
+	
+}   /* End of hexdata */
+
+/*****************************************************************************/
+
+getint()
+
+{
+
+    int		val;
+
+/*
+ *
+ * Reads the next four bytes into an integer and returns the value to the caller.
+ * First two bytes are probably always 0.
+ *
+ */
+
+    val = getc(fp_in);
+    val |= (getc(fp_in) << 8);
+    val |= (getc(fp_in) << 16);
+    val |= (getc(fp_in) << 24);
+
+    return(val);
+
+}   /* End of getint */ 
+
+/*****************************************************************************/
+
+error(kind, mesg, a1, a2, a3)
+
+    int		kind;
+    char	*mesg;
+    unsigned	a1, a2, a3;
+
+{
+
+/*
+ *
+ * Print mesg and quit if kind is FATAL.
+ *
+ */
+
+    if ( mesg != NULL && *mesg != '\0' ) {
+	fprintf(stderr, "%s: ", prog_name);
+	fprintf(stderr, mesg, a1, a2, a3);
+	putc('\n', stderr);
+    }	/* End if */
+
+    if ( kind == FATAL && ignore == OFF )
+	exit(x_stat | 01);
+
+}   /* End of error */
+
+/*****************************************************************************/
+
diff --git a/src/cmd/postscript/misc/laserbar.1 b/src/cmd/postscript/misc/laserbar.1
new file mode 100644
index 0000000..e845fc9
--- /dev/null
+++ b/src/cmd/postscript/misc/laserbar.1
@@ -0,0 +1,41 @@
+.TH LASERBAR 1
+.SH NAME
+laserbar \- produce bar codes on a PostScript laser printer
+.SH SYNOPSIS
+.B laserbar
+[\fB-r\fP rotate] [\fB-x\fP xoffset] [\fB-y\fP yoffset]
+[\fB-X\fP xscale] [\fB-Y\fP yscale] [\fB-lns\fP] string
+.SH DESCRIPTION
+.I Laserbar
+prints on the standard output the PostScript text that will produce
+(on a suitable laser printer) the \s-2CODE-39\s+2 bar code
+corresponding to
+.I string.
+The \fBr\fP option may be used to specify a rotation (in
+degrees) of the bar code.
+The \fBx\fP, \fBy\fP, \fBX\fP, and \fBY\fP options may be used to specify
+an x- or y-axis offset (in inches) or scaling factor, respectively.
+(The offset is measured from the lower left corner of the page
+to the upper left corner of the bar
+code.  By default, the bar code produced is one inch high, and is scaled
+so that the narrowest elements are each 1/72-inch \- i.e., one point \- wide.)
+If the \fBl\fP option is specified, the bar code produced is labeled.
+If the \fBn\fP option is specified, the resulting PostScript text
+includes a leading \f(CWnewpath\fP command, so that the text may stand
+alone or precede any other PostScript commands.
+If the \fBs\fP option is specified, the resulting PostScript text includes 
+a trailing \f(CWshowpage\fP command, so that the text may stand alone
+or follow any other PostScript commands.
+.P
+This manual page (if it appears with a bar code printed on it) was
+produced by something like the following sequence:
+.IP
+.ft CW
+laserbar -x 2.5 -y 3 -l -n ABC123xyz > tempfile
+.br
+troff -man -Tpost laserbar.1 | dpost >> tempfile
+.br
+prt -dprinter -lpostscript tempfile
+.ft P
+.SH SEE ALSO
+laserbar(3), prt(1), dpost(1), postbgi(1), postprint(1), postdmd(1), posttek(1), etc.
diff --git a/src/cmd/postscript/misc/laserbar.c b/src/cmd/postscript/misc/laserbar.c
new file mode 100644
index 0000000..2f61c27
--- /dev/null
+++ b/src/cmd/postscript/misc/laserbar.c
@@ -0,0 +1,166 @@
+/* laserbar -- filter to print barcodes on postscript printer */
+
+#define MAIN 1
+
+#define	LABEL	01
+#define	NFLAG	02
+#define	SFLAG	04
+
+#include <stdio.h>
+#include <ctype.h>
+
+static int code39[256] = {
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/*	sp    !     "     #     $     %     &     '	*/
+	0304, 0,    0,    0,    0250, 0052, 0,    0,   
+/*	(     )     *     +     ,     -     -     /	*/
+	0,    0,    0224, 0212, 0,    0205, 0604, 0242,
+/*	0     1     2     3     4     5     6     7	*/
+	0064, 0441, 0141, 0540, 0061, 0460, 0160, 0045,
+/*	8     9     :     ;     <     =     >     ?	*/
+	0444, 0144, 0,    0,    0,    0,    0,    0,   
+/*	@     A     B     C     D     E     F     G	*/
+	0,    0411, 0111, 0510, 0031, 0430, 0130, 0015,
+/*	H     I     J     K     L     M     N     O	*/
+	0414, 0114, 0034, 0403, 0103, 0502, 0023, 0422,
+/*	P     Q     R     S     T     U     V     W	*/
+	0122, 0007, 0406, 0106, 0026, 0601, 0301, 0700,
+/*	X     Y     Z     [     \     ]     ^     _	*/
+	0221, 0620, 0320, 0,    0,    0,    0,    0,
+/*	`     a     b     c     d     e     f     g	*/
+	0,    0411, 0111, 0510, 0031, 0430, 0130, 0015,
+/*	h     i     j     k     l     m     n     o	*/
+	0414, 0114, 0034, 0403, 0103, 0502, 0023, 0422,
+/*	p     q     r     s     t     u     v     w	*/
+	0122, 0007, 0406, 0106, 0026, 0601, 0301, 0700,
+/*	x     y     z     {     |     }     ~     del	*/
+	0221, 0620, 0320, 0,    0,    0,    0,    0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void barprt();
+void laserbar();
+
+#ifdef MAIN
+
+main(argc, argv)
+char **argv;
+{
+	int c, flags = 0, error = 0;
+	double rotate = 0, xoffset = 0, yoffset = 0, xscale = 1, yscale = 1;
+	extern char *optarg;
+	extern int optind;
+	extern double atof();
+	extern void exit();
+
+	while ((c = getopt(argc, argv, "r:x:y:X:Y:lns")) != EOF) {
+		switch(c) {
+		    case 'r':
+			rotate = atof(optarg);
+			break;
+		    case 'x':
+			xoffset = atof(optarg);
+			break;
+		    case 'y':
+			yoffset = atof(optarg);
+			break;
+		    case 'X':
+			xscale = atof(optarg);
+			break;
+		    case 'Y':
+			yscale = atof(optarg);
+			break;
+		    case 'l':
+			flags |= LABEL;
+			break;
+		    case 'n':
+			flags |= NFLAG;
+			break;
+		    case 's':
+			flags |= SFLAG;
+			break;
+		    case '?':
+			++error;
+		}
+	}
+	if ((argc - optind) != 1)
+		++error;
+	if (error) {
+		(void) fprintf(stderr,
+"Usage: %s [-r rotate] [-x xoffset] [-y yoffset] [-X xscale] [-Y yscale] [-lns] string\n",
+		    *argv);
+		exit(1);
+	}
+	laserbar(stdout, argv[optind], rotate, xoffset, yoffset, xscale, yscale, flags);
+	return 0;
+}
+
+#endif /*MAIN*/
+
+static int right = 0;
+
+void
+laserbar(fp, str, rotate, xoffset, yoffset, xscale, yscale, flags)
+FILE *fp;
+char *str;
+double rotate, xoffset, yoffset, xscale, yscale;
+int flags;
+{
+	xoffset *= 72.;
+	yoffset *= 72.;
+	(void) fprintf(fp, "gsave %s\n", (flags & NFLAG) ? "newpath" : "");
+	if (xoffset || yoffset)
+		(void) fprintf(fp, "%f %f moveto\n", xoffset, yoffset);
+	if (xscale != 1 || yscale != 1)
+		(void) fprintf(fp, "%f %f scale\n", xscale, yscale);
+	if (rotate)
+		(void) fprintf(fp, "%f rotate\n", rotate);
+	(void) fputs("/Helvetica findfont 16 scalefont setfont\n", fp);
+	(void) fputs("/w { 0 rmoveto gsave 3 setlinewidth 0 -72 rlineto stroke grestore } def\n", fp);
+	(void) fputs("/n { 0 rmoveto gsave 1 setlinewidth 0 -72 rlineto stroke grestore } def\n", fp);
+	(void) fputs("/l { gsave 2 -88 rmoveto show grestore } def\n", fp);
+	barprt(fp, '*', 0);
+	while (*str)
+		barprt(fp, *(str++), (flags & LABEL));
+	barprt(fp, '*', 0);
+	(void) fprintf(fp, "%sgrestore\n", (flags & SFLAG) ? "showpage " : "");
+	right = 0;
+}
+
+static void
+barprt(fp, c, label)
+FILE *fp;
+int c, label;
+{
+	int i, mask, bar, wide;
+
+	if (!(i = code39[c]))
+		return;
+	if (islower(c))
+		c = toupper(c);
+	if (label)
+		(void) fprintf(fp, "(%c) l", c);
+	else
+		(void) fputs("     ", fp);
+	for (bar = 1, mask = 0400; mask; bar = 1 - bar, mask >>= 1) {
+		wide = mask & i;
+		if (bar) {
+			if (wide)
+				++right;
+			(void) fprintf(fp, " %d %s", right, wide ? "w" : "n");
+			right = (wide ? 2 : 1);
+		}
+		else
+			right += (wide ? 3 : 1);
+	}
+	(void) fputs("\n", fp);
+	++right;
+}
diff --git a/src/cmd/postscript/misc/lp.model b/src/cmd/postscript/misc/lp.model
new file mode 100644
index 0000000..966621e
--- /dev/null
+++ b/src/cmd/postscript/misc/lp.model
@@ -0,0 +1,66 @@
+
+#       qmsps800        mac 10/22/86
+#
+LPDEST=`basename $0`
+QMS_FILE="$1"
+DATE="`date +%D`"
+TIME="`date +%T`"
+owner="$2"
+site=`uname`
+port="`/usr/bin/lpstat -v$LPDEST | sed -e 's/.*: //'`"
+filter_cmd="/usr/lbin/postscript/postio"
+filter="$filter_cmd -l $port"
+landscape="" formsperpage=""
+path=/usr/lbin/postscript
+printer=postprint
+bannerflag=ON
+prev="| $path/postreverse"
+
+for i in $5
+do
+        case "$i" in
+                L2)
+                        formsperpage="-n2"
+                        ;;
+                land)
+                        landscape="-pland"
+                        ;;
+                dpost|postprint|posttek|postbgi|postdmd|postio)
+                        printer="$i"
+                        ;;
+
+                postreverse)
+                        prev=""
+                        ;;
+                nobanner)
+                        bannerflag=OFF
+                        ;;
+                F*)
+                        QMS_FILE="`expr $i : 'F\(.*\)'`"
+                        ;;
+        esac
+done
+
+if [ -n "$filter_cmd" -a ! -x "$filter_cmd" ]
+then
+        disable -r"can't execute filter: $filter_cmd" $LPDEST
+        exit 1
+fi
+
+shift; shift; shift; shift; shift
+files="$*"
+cp /usr/spool/lp/model/banner.ps /tmp/ban.$$
+echo "($QMS_FILE) ($LPDEST) ($TIME) ($DATE) ($owner) banner" >> /tmp/ban.$$
+if [ "$printer" = "postio" ]
+        then
+        eval $filter $files 2> /dev/null
+else
+        eval $path/$printer $landscape $formsperpage $files $prev | $filter 2> /dev/null
+        fi
+if [ "$bannerflag" = "ON" ]
+        then
+        eval $filter /tmp/ban.$$ 2> /dev/null
+        fi
+rm -f /tmp/ban.$$
+exit 0
+
diff --git a/src/cmd/postscript/misc/macfont.c b/src/cmd/postscript/misc/macfont.c
new file mode 100644
index 0000000..59244a1
--- /dev/null
+++ b/src/cmd/postscript/misc/macfont.c
@@ -0,0 +1,299 @@
+/*
+ *
+ * Program that converts Macintosh font files to a format that works on Unix
+ * systems. Essentially all the information needed came from the Adobe paper
+ * "Supporting Downloadable PostScript Fonts". To use the program type,
+ *
+ *	macfont font.mac >font.unix
+ *
+ * where font.mac is the font file, exactly as it came over from a Macintosh,
+ * and font.unix is equivalent host resident font file usable on Unix systems.
+ * 
+ */
+
+#include <stdio.h>
+#include <signal.h>
+
+#define OFF		0
+#define ON		1
+
+#define NON_FATAL	0
+#define FATAL		1
+
+#define FALSE		0
+#define TRUE		1
+
+char	**argv;
+int	argc;
+
+char	*prog_name;
+
+int	x_stat;
+int	debug = OFF;
+int	ignore = OFF;
+
+FILE	*fp_in;
+FILE	*fp_out;
+
+/*****************************************************************************/
+
+main(agc, agv)
+
+    int		agc;
+    char	*agv[];
+
+{
+
+/*
+ *
+ * Macintosh to Unix font converter.
+ *
+ */
+
+    argc = agc;
+    argv = agv;
+    prog_name = argv[0];
+
+    fp_in = stdin;
+    fp_out = stdout;
+
+    options();
+    arguments();
+    exit(x_stat);
+
+}   /* End of main */
+
+/*****************************************************************************/
+
+options()
+
+{
+
+    int		ch;
+    char	*names = "DI";
+
+    extern char	*optarg;
+    extern int	optind;
+
+/*
+ *
+ * Command line options.
+ *
+ */
+
+    while ( (ch = getopt(argc, argv, names)) != EOF ) {
+	switch ( ch ) {
+	    case 'D':			/* debug flag */
+		    debug = ON;
+		    break;
+
+	    case 'I':			/* ignore FATAL errors */
+		    ignore = ON;
+		    break;
+
+	    case '?':			/* don't understand the option */
+		    error(FATAL, "");
+		    break;
+
+	    default:			/* don't know what to do for ch */
+		    error(FATAL, "missing case for option %c\n", ch);
+		    break;
+	}   /* End switch */
+    }   /* End while */
+
+    argc -= optind;
+    argv += optind;
+
+}   /* End of options */
+
+/*****************************************************************************/
+
+arguments()
+
+{
+
+
+/*
+ *
+ * Everything else is an input file. No arguments or '-' means stdin.
+ *
+ */
+
+    if ( argc < 1 )
+	conv();
+    else
+	while ( argc > 0 ) {
+	    if ( strcmp(*argv, "-") == 0 )
+		fp_in = stdin;
+	    else if ( (fp_in = fopen(*argv, "r")) == NULL )
+		error(FATAL, "can't open %s", *argv);
+	    conv();
+	    if ( fp_in != stdin )
+		fclose(fp_in);
+	    argc--;
+	    argv++;
+	}   /* End while */
+
+}   /* End of arguments */
+
+/*****************************************************************************/
+
+conv()
+
+{
+
+    int		blocksize;
+    int		blocktype;
+
+/*
+ *
+ * The first four bytes (in a block) are the block size, the fifth is the block
+ * type, and the sixth always appears to be NULL. Type 0 blocks are comments and
+ * are always skipped. Type 1 blocks are ASCII text, type 2 is binary data that
+ * should be converted to hex, while type 5 blocks represent the end of the font
+ * file. Commment block lengths appear to be from the first byte, while other
+ * lengths seem to be measured from block type byte (ie. the fifth byte). Type
+ * four blocks aren't used, while type 3 blocks mean an end of file indication
+ * should be sent to the printer. Haven't done anything with type 3 blocks.
+ *
+ */
+
+    while ( 1 ) {
+	blocksize = getint(fp_in);
+	blocktype = getc(fp_in);
+	getc(fp_in);
+	if ( debug == ON )
+	    fprintf(stderr, "blocktype = %d, blocksize = %d\n", blocktype, blocksize);
+	switch ( blocktype ) {
+	    case 0:			/* comment - skip blockcount bytes */
+		fseek(fp_in, (long) blocksize - 6, 1);
+		break;
+
+	    case 1:
+		asciitext(blocksize - 2);
+		break;
+
+	    case 2:
+		hexdata(blocksize - 2);
+		break;
+
+	    case 3:
+	    case 4:
+		error(FATAL, "resource type %d not implemented", blocktype);
+		break;
+
+	    case 5:
+		return;
+
+	    default:
+		error(FATAL, "unknown resource type %d", blocktype);
+	}   /* End switch */
+    }	/* End while */
+
+}   /* End of conv */
+
+/*****************************************************************************/
+
+asciitext(count)
+
+    int		count;			/* bytes left in the block */
+
+{
+
+    int		ch;
+    int		i = 0;
+
+/*
+ *
+ * Handles type 1 (ie. ASCII text) blocks. Changing carriage returns to newlines
+ * is all I've done.
+ *
+ */
+
+    for ( i = 0; i < count; i++ ) {
+	if ( (ch = getc(fp_in)) == '\r' )
+	    ch = '\n';
+	putc(ch, fp_out);
+    }	/* End for */
+	
+}   /* End of asciitext */
+
+/*****************************************************************************/
+
+hexdata(count)
+
+    int		count;			/* bytes left in the block */
+
+{
+
+    int		i;
+    int		n;
+
+/*
+ *
+ * Reads the next count bytes and converts each byte to hex. Also starts a new
+ * line every 80 hex characters.
+ *
+ */
+
+    for ( i = 0, n = 0; i < count; i++ ) {
+	fprintf(fp_out, "%.2X", getc(fp_in));
+	if ( (++n % 40) == 0 )
+	    putc('\n', fp_out);
+    }	/* End for */
+	
+}   /* End of hexdata */
+
+/*****************************************************************************/
+
+getint()
+
+{
+
+    int		val;
+    int		i;
+
+/*
+ *
+ * Reads the next four bytes into an integer and returns the value to the caller.
+ * First two bytes are probably always 0.
+ *
+ */
+
+    for ( i = 0, val = (getc(fp_in) & 0377); i < 3; i++ )
+	val = (val << 8) | (getc(fp_in) & 0377);
+
+    return(val);
+
+}   /* End of getint */ 
+
+/*****************************************************************************/
+
+error(kind, mesg, a1, a2, a3)
+
+
+    int		kind;
+    char	*mesg;
+    unsigned	a1, a2, a3;
+
+{
+
+/*
+ *
+ * Print *mesg then quit if kind is FATAL.
+ *
+ */
+
+    if ( mesg != NULL && *mesg != '\0' ) {
+	fprintf(stderr, "%s: ", prog_name);
+	fprintf(stderr, mesg, a1, a2, a3);
+	putc('\n', stderr);
+    }	/* End if */
+
+    if ( kind == FATAL && ignore == OFF )
+	exit(x_stat | 01);
+
+}   /* End of error */
+
+/*****************************************************************************/
+
diff --git a/src/cmd/postscript/misc/pscrypt.c b/src/cmd/postscript/misc/pscrypt.c
new file mode 100644
index 0000000..1715288
--- /dev/null
+++ b/src/cmd/postscript/misc/pscrypt.c
@@ -0,0 +1,335 @@
+/*
+ *
+ * Adobe's encryption/decryption algorithm for eexec and show. Runs in
+ * eexec mode unless told otherwise. Use,
+ *
+ *		pscrypt file.cypher > file.clear
+ *
+ * to decrypt eexec input. Assumes file.cypher is hex with the key as the
+ * first four bytes, and writes file.clear as binary (omitting the key).
+ * Use
+ *
+ *		pscrypt -e12ab34ef file.clear >file.cypher
+ *
+ * to encrypt file.clear (for eexec) using 12ab34ef as the key. Input is
+ * binary and output is hex. The key must be given as a hex number. Use
+ * -sshow to encrypt or decrypt a CharString or Subr,
+ *
+ *		pscrypt -sshow file.cypher > file.clear
+ *
+ * Use -b or -x to read binary or hex input, and -B or -X to output binary
+ * or hex.
+ *
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#define ENCRYPT		0
+#define DECRYPT		1
+
+#define NOTSET		-1
+#define BINARY		0
+#define HEX		1
+#define LINELENGTH	40
+
+#define CHARSTRING	4330
+#define EEXEC		55665
+#define MAGIC1		52845
+#define MAGIC2		22719
+
+int	argc;
+char	**argv;
+
+int	mode = DECRYPT;
+int	input = NOTSET;
+int	output = NOTSET;
+int	outoffset = NOTSET;
+int	inoffset = NOTSET;
+
+int	cryptkey = 0;			/* encryption key set with -e */
+int	linelength = LINELENGTH;	/* only for hex output */
+int	lastchar = 0;
+
+unsigned long	seed = EEXEC;
+unsigned long	key;
+
+FILE	*fp_in;
+
+/*****************************************************************************/
+
+main(agc, agv)
+
+    int		agc;
+    char	*agv[];
+
+{
+
+/*
+ *
+ * Implementation of the encryption/decryption used by eexec and show.
+ *
+ */
+
+    argc = agc;
+    argv = agv;
+
+    fp_in = stdin;
+
+    options();
+    initialize();
+    arguments();
+
+    exit(0);
+
+}   /* End of main */
+
+/*****************************************************************************/
+
+options()
+
+{
+
+    int		ch;
+    char	*names = "bde:l:os:xBSX";
+
+    extern char	*optarg;
+    extern int	optind;
+
+/*
+ *
+ * Command line options.
+ *
+ */
+
+    while ( (ch = getopt(argc, argv, names)) != EOF )
+	switch ( ch ) {
+	    case 'b':			/* binary input */
+		    input = BINARY;
+		    break;
+
+	    case 'd':			/* decrypt */
+		    mode = DECRYPT;
+		    break;
+
+	    case 'e':			/* encrypt */
+		    mode = ENCRYPT;
+		    if ( *optarg == '0' && *optarg == 'x' )
+			optarg += 2;
+		    sscanf(optarg, "%8x", &cryptkey);
+		    break;
+
+	    case 'l':			/* line length hex output */
+		    linelength = atoi(optarg);
+		    break;
+
+	    case 'o':			/* output all bytes - debugging */
+		    outoffset = 0;
+		    break;
+
+	    case 's':			/* seed */
+		    if ( *optarg == 'e' )
+			seed = EEXEC;
+		    else if ( *optarg == 's' )
+			seed = CHARSTRING;
+		    else if ( *optarg == '0' && *(optarg+1) == 'x' )
+			sscanf(optarg+2, "%x", &seed);
+		    else if ( *optarg == '0' )
+			sscanf(optarg, "%o", &seed);
+		    else sscanf(optarg, "%d", &seed);
+		    break;
+
+	    case 'x':			/* hex input */
+		    input = HEX;
+		    break;
+
+	    case 'B':			/* binary output */
+		    output = BINARY;
+		    break;
+
+	    case 'X':			/* hex output */
+		    output = HEX;
+		    break;
+
+	    case '?':			/* don't understand the option */
+		    fprintf(stderr, "bad option -%c\n", ch);
+		    exit(1);
+		    break;
+
+	    default:			/* don't know what to do for ch */
+		    fprintf(stderr, "missing case for option -%c\n", ch);
+		    exit(1);
+		    break;
+	}   /* End switch */
+
+    argc -= optind;			/* get ready for non-option args */
+    argv += optind;
+
+}   /* End of options */
+
+/*****************************************************************************/
+
+initialize()
+
+{
+
+/*
+ *
+ * Initialization that has to be done after the options.
+ *
+ */
+
+    key = seed;
+
+    if ( mode == DECRYPT ) {
+	input = (input == NOTSET) ? HEX : input;
+	output = (output == NOTSET) ? BINARY : output;
+	inoffset = (inoffset == NOTSET) ? 0 : inoffset;
+	outoffset = (outoffset == NOTSET) ? -4 : outoffset;
+    } else {
+	input = (input == NOTSET) ? BINARY : input;
+	output = (output == NOTSET) ? HEX : output;
+	inoffset = (inoffset == NOTSET) ? 4 : inoffset;
+	outoffset = (outoffset == NOTSET) ? 0 : outoffset;
+    }	/* End else */
+
+    if ( linelength <= 0 )
+	linelength = LINELENGTH;
+
+}   /* End of initialize */
+
+/*****************************************************************************/
+
+arguments()
+
+{
+
+/*
+ *
+ * Everything left is an input file. No arguments or '-' means stdin.
+ *
+ */
+
+    if ( argc < 1 )
+	crypt();
+    else
+	while ( argc > 0 ) {
+	    if ( strcmp(*argv, "-") == 0 )
+		fp_in = stdin;
+	    else if ( (fp_in = fopen(*argv, "r")) == NULL ) {
+		fprintf(stderr, "can't open %s\n", *argv);
+		exit(1);
+	    }	/* End if */
+	    crypt();
+	    if ( fp_in != stdin )
+		fclose(fp_in);
+	    argc--;
+	    argv++;
+	}   /* End while */
+
+}   /* End of arguments */
+
+/*****************************************************************************/
+
+crypt()
+
+{
+
+    unsigned int	cypher;
+    unsigned int	clear;
+
+/*
+ *
+ * Runs the encryption/decryption algorithm.
+ *
+ */
+
+    while ( lastchar != EOF ) {
+	cypher = nextbyte();
+	clear = ((key >> 8) ^ cypher) & 0xFF;
+	key = (key + (mode == DECRYPT ? cypher : clear)) * MAGIC1 + MAGIC2;
+	if ( ++outoffset > 0 && lastchar != EOF ) {
+	    if ( output == HEX ) {
+		printf("%.2X", clear);
+		if ( linelength > 0 && (outoffset % linelength) == 0 )
+		    putchar('\n');
+	    } else putchar(clear);
+	}   /* End if */
+    }	/* End while */
+
+}   /* End of crypt */
+
+/*****************************************************************************/
+
+nextbyte()
+
+{
+
+    int		val = EOF;
+
+/*
+ *
+ * Returns the next byte. Uses cryptkey (i.e. what followed -e) while inoffset is
+ * positive, otherwise reads (hex or binary) from fp_in.
+ *
+ */
+
+    if ( inoffset-- > 0 )
+	val = (cryptkey >> (inoffset*8)) & 0xFF;
+    else if ( input == HEX ) {
+	if ( (val = nexthexchar()) != EOF )
+	    val = (val << 4) | nexthexchar();
+    } else if ( input == BINARY )
+	val = Getc(fp_in);
+
+    return(val);
+
+}   /* End of nextbyte */
+
+/*****************************************************************************/
+
+nexthexchar()
+
+{
+
+    int		ch;
+
+/*
+ *
+ * Reads the next hex character.
+ *
+ */
+
+    while ( (ch = Getc(fp_in)) != EOF && ! isxdigit(ch) ) ;
+
+    if ( isdigit(ch) )
+	ch -= '0';
+    else if ( isupper(ch) )
+	ch -= 'A' - 10;
+    else if ( islower(ch) )
+	ch -= 'a' - 10;
+
+    return(ch);
+
+}   /* End of nexthexchar */
+
+/*****************************************************************************/
+
+Getc(fp)
+
+    FILE	*fp;
+
+{
+
+/*
+ *
+ * Reads the next byte from *fp, sets lastchar, and returns the character.
+ *
+ */
+
+    return(lastchar = getc(fp));
+
+}   /* End of Getc */
+
+/*****************************************************************************/
+
diff --git a/src/cmd/postscript/misc/setbaud.ps b/src/cmd/postscript/misc/setbaud.ps
new file mode 100644
index 0000000..93148d0
--- /dev/null
+++ b/src/cmd/postscript/misc/setbaud.ps
@@ -0,0 +1,9 @@
+%
+% Sets baud rate to 9600, options to 0 assuming the password is 0.
+%
+
+serverdict begin
+	0 exitserver
+	statusdict begin
+		25 9600 0 setsccbatch
+	end
diff --git a/src/cmd/postscript/mkfile b/src/cmd/postscript/mkfile
index 158be81..cf6d3ac 100644
--- a/src/cmd/postscript/mkfile
+++ b/src/cmd/postscript/mkfile
@@ -14,7 +14,7 @@
 #	postprint\
 #	postreverse\
 #	posttek\
-#	printfont\
+	printfont\
 #	psencoding\
 #	psfiles\
 #	g3p9bit\
diff --git a/src/cmd/postscript/mpictures/.cvsignore b/src/cmd/postscript/mpictures/.cvsignore
new file mode 100644
index 0000000..b352e03
--- /dev/null
+++ b/src/cmd/postscript/mpictures/.cvsignore
@@ -0,0 +1 @@
+tmac.pictures
diff --git a/src/cmd/postscript/mpictures/mkfile b/src/cmd/postscript/mpictures/mkfile
new file mode 100644
index 0000000..cc4d48c
--- /dev/null
+++ b/src/cmd/postscript/mpictures/mkfile
@@ -0,0 +1,18 @@
+</$objtype/mkfile
+
+<../config
+
+TMACDIR=/sys/lib/tmac
+
+all:V:	tmac.pictures
+
+install installall:V:	$TMACDIR/tmac.pictures
+
+clean nuke:V:
+	rm -f tmac.pictures
+
+$TMACDIR/tmac.pictures:	tmac.pictures
+	cp $prereq $target
+
+tmac.pictures : pictures.sr
+	cp $prereq $target
diff --git a/src/cmd/postscript/mpictures/pictures.sr b/src/cmd/postscript/mpictures/pictures.sr
new file mode 100644
index 0000000..6ff4f96
--- /dev/null
+++ b/src/cmd/postscript/mpictures/pictures.sr
@@ -0,0 +1,154 @@
+.de PI	\" Picture Include
+.	\" $1=file(page) $2=height,width,yoff,xoff $3=flags
+.	\" Height, width, xoff, and yoff are for the frame, flags is for the
+.	\" picture. Default dimensions are inches.
+\\X'PI:\\n(.o:\\n(.i:\\n(.l:\\n(.t:\\$1:\\$2:\\$3:'\\c
+..
+.nr FT 0
+.de BP	\" Begin a Picture
+.	\"
+.	\" $1=file(page) $2=height $3=width $4=position $5=offset $6=flags $7=label
+.	\"
+.	\" Height, width, position, and offset are for the frame, flags is for
+.	\" the picture. The postion flag should be l, c, r, or "". Omitting the
+.	\" position argument is also allowed for compatibility with the original
+.	\" version of the macro. In that case offset is taken relative to your
+.	\" left margin.
+.if \\n(FT>1 .EP
+.	\" Need these when we switch environments.
+.nr Ov \\n(.v
+.nr Oi \\n(.i
+.nr Ol \\n(.l
+.	\" Remember the arguments - sometimes as both a string and number register.
+.nr $2 \\$2i
+.nr $3 \\$3i
+.nr $4 \\$4i
+.ds $4 \\$4
+.nr $5 \\$5i
+.ds $5 \\$6
+.ds $6 \\$7
+.	\" Accept a few unadvertised position flags.
+.if '\\*($4'L' .ds $4 l
+.if '\\*($4'C' .ds $4 c
+.if '\\*($4'R' .ds $4 r
+.	\" A null with more than three arguments means l.
+.if \\n(.$>3 .if '\\*($4'' .ds $4 l
+.	\" Default frame dimensions if missing, zero, or null.
+.if !\\n($2>0 .nr $2 3.0i
+.if !\\n($3>0 .nr $3 \\n(.lu-\\n(.iu-\\n($4u
+.if !\\n($3>0 .nr $3 \\n($2u
+.	\" Figure out the offset that will be used the rest of the way.
+.if '\\*($4'l' .nr $4 \\n($5u
+.if '\\*($4'c' .nr $4 (\\n(.lu-\\n(.iu-\\n($3u)/2u+\\n($5u
+.if '\\*($4'r' .nr $4 \\n(.lu-\\n(.iu-\\n($3u+\\n($5u
+.	\" If we haven't recognized the position flag assume it wasn't given and
+.	\" treat argument four as an offset from the left.
+.if !'\\*($4'l' .if !'\\*($4'c' .if !'\\*($4'r' .ds $5 \\$5
+.if !'\\*($4'l' .if !'\\*($4'c' .if !'\\*($4'r' .ds $6 \\$6
+.	\" Set increments for line length and indent.
+.nr Ii \\n($3u+\\n($4u+.1i
+.nr Il \\n(.lu-\\n(.iu-\\n($4u+.1i
+.	\" Set the frame type to one of:
+.	\"	0 - frame is as wide as a line of text - skip over it.
+.	\"	1 - fits in left or right margins
+.	\"	2 - fill with text on the right
+.	\"	3 - on the left
+.	\"	4 - or on both sides of the frame
+.	\"	5 - only set in EP if FT was 4 and now filling on the right.
+.	\" Assume the frame is as wide as a line of text, then check dimensions
+.	\" to see what's really true. The order of these tests is important!
+.nr FT 0
+.if \\n($4u>1.0i .nr FT 3
+.if \\n($4u+\\n(.iu>=\\n(.lu .nr FT 1
+.if \\n($3u+\\n($4u+\\n(.iu+1.0i<\\n(.lu .nr FT 2
+.if \\n($3u+\\n($4u<=0 .nr FT 1
+.if \\n(FT=2 .if \\n($4u>1.0i .nr FT 4
+.	\" Ask for some vertical space - labeled pictures need a little extra,
+.	\" margin pictures a little less.
+.if \\n(FT=1 .if '\\*($6'' .ne \\n($2u
+.if \\n(FT=1 .if !'\\*($6'' .ne \\n($2u+2v
+.if !\\n(FT=1 .if '\\*($6'' .ne \\n($2u+3v
+.if !\\n(FT=1 .if !'\\*($6'' .ne \\n($2u+5v
+.	\" Save our place, draw the picture, label it, and return. Need precise
+.	\" control of when \X'...' is put out - thus the new environment.
+.mk Oh
+.ev 1
+.in \\n(Oiu
+.ll \\n(Olu
+.vs \\n(Ovu
+.if \\n(FT=1 .sp -1v
+.if \\n(FT=1 .PI \\$1 \\n($2u,\\n($3u,\\n(.vu,\\n($4u t\\*($5
+.if !\\n(FT=1 .PI \\$1 \\n($2u,\\n($3u,\\n(.vu,\\n($4u \\*($5
+.in
+.ll
+.vs
+.ev
+.lt \\n($3u
+.tl \(ts\(ts\\h'\\n($4u+\\n(.iu'\\v'\\n($2u+1.5v'\\*($6\\v'-\\n($2u-1.5v'\\h'-\\n($4u-\\n(.iu'\(ts\(ts
+.lt
+'sp |\\n(Ohu
+.	\" Figure out what to do with the text that follows.
+.if !'\\*($6'' .nr $2 +2v
+.if \\n(FT=0 .sp \\n($2u+2v
+.if \\n(FT=1 .nr FT 0
+.if \\n(FT=2 'in +\\n(Iiu
+.if \\n(FT>2 .ll -\\n(Ilu
+.if \\n(FT>1 .di BB
+.if \\n(FT>1 .dt \\n($2u+2v+1u EP
+.	\" Clean things up.
+.rr $2
+.rr $3
+.rr $4
+.rm $4
+.rr $5
+.rm $5
+.rm $6
+.rr Oh
+.rr Oi
+.rr Ol
+.rr Ov
+.if \\n(FT=0 .EP
+..
+.de EP	\" End the Picture - Normally called from a trap, although it can be used
+.	\" on its own to mark the end of a picture.
+.nr Ot 0
+.if \\n(.tu<\\n(.pu .nr Ot \\n(.tu
+.if \\n(Ot>0 .if \\n(FT=4 .nr FT 3
+.if \\n(FT<2 .nr Ot 0
+.if \\n(Ot>0 .br
+.if \\n(FT=5 .nr Ot 0
+.if \\n(FT>1 \{\
+.	ev 1
+.	eo
+.	br
+.	di
+.	nf
+.	in 0
+.	BB
+.	in
+.	fi
+.	ec
+.	ev
+.	rm BB\}
+.if \\n(FT=5 \{\
+.	nr FT 2
+'	sp |\\n(Nhu+1v\}
+.if \\n(FT=4 \{\
+.	mk Nh
+.	nr Nh -1v
+.	nr FT 5
+'	sp -\\n(dnu+1v
+'	in +\\n(Iiu
+.	ll +\\n(Ilu
+.	di BB
+.	dt \\n(dnu-2v+1u EP\}
+.if \\n(FT=2 'in -\\n(Iiu
+.if \\n(FT=3 .ll +\\n(Ilu
+.if \\n(FT<4 .nr FT 0
+.if \\n(Ot>0 .sp \\n(Otu
+.rr Ot
+.if \\n(FT=0 \{\
+.	rr Nh
+.	rr Ii
+.	rr Il\}
+..
diff --git a/src/cmd/postscript/postreverse/.cvsignore b/src/cmd/postscript/postreverse/.cvsignore
new file mode 100644
index 0000000..ce6f874
--- /dev/null
+++ b/src/cmd/postscript/postreverse/.cvsignore
@@ -0,0 +1 @@
+postreverse
diff --git a/src/cmd/postscript/postreverse/README b/src/cmd/postscript/postreverse/README
new file mode 100644
index 0000000..d7038ae
--- /dev/null
+++ b/src/cmd/postscript/postreverse/README
@@ -0,0 +1,10 @@
+
+A simple program that reverses the pages in PostScript files that
+conform to Adobe's Version 1.0 or Version 2.0 file structuring
+conventions.
+
+postrevese also handles a small class of files that violate page
+independence (eg. output from dpost) and can be used with all the
+translators in this package. The output can be conforming even if
+the input file wasn't.
+
diff --git a/src/cmd/postscript/postreverse/mkfile b/src/cmd/postscript/postreverse/mkfile
new file mode 100644
index 0000000..0e935e8
--- /dev/null
+++ b/src/cmd/postscript/postreverse/mkfile
@@ -0,0 +1,29 @@
+</$objtype/mkfile
+
+<../config
+
+COMMONDIR=../common
+
+TARG=postreverse
+
+OFILES=postreverse.$O\
+
+HFILES=postreverse.h\
+	$COMMONDIR/comments.h\
+	$COMMONDIR/ext.h\
+	$COMMONDIR/gen.h\
+	$COMMONDIR/path.h\
+
+BIN=$POSTBIN
+LIB=$COMMONDIR/com.a$O
+
+</sys/src/cmd/mkone
+
+CC=pcc
+LD=pcc
+CFLAGS=-c -D$SYSTEM -D_POSIX_SOURCE -I$COMMONDIR -B
+
+$LIB:
+	cd $COMMONDIR
+	mk install
+	mk clean
diff --git a/src/cmd/postscript/postreverse/postreverse.c b/src/cmd/postscript/postreverse/postreverse.c
new file mode 100644
index 0000000..d99124d
--- /dev/null
+++ b/src/cmd/postscript/postreverse/postreverse.c
@@ -0,0 +1,544 @@
+/*
+ *
+ * postreverse - reverse the page order in certain PostScript files.
+ *
+ * Page reversal relies on being able to locate sections of a document using file
+ * structuring comments defined by Adobe (ie. the 1.0 and now 2.0 conventions) and
+ * a few I've added. Among other things a minimally conforming document, according
+ * to the 1.0 conventions,
+ *
+ *	1) Marks the end of the prologue with an %%EndProlog comment.
+ *
+ *	2) Starts each page with a %%Page: comment.
+ *
+ *	3) Marks the end of all the pages %%Trailer comment.
+ *
+ *	4) Obeys page independence (ie. pages can be arbitrarily rearranged).
+ *
+ * The most important change (at least for this program) that Adobe made in going
+ * from the 1.0 to the 2.0 structuring conventions was in the prologue. They now
+ * say the prologue should only define things, and the global initialization that
+ * was in the prologue (1.0 conventions) should now come after the %%EndProlog
+ * comment but before the first %%Page: comment and be bracketed by %%BeginSetup
+ * and %%EndSetup comments. So a document that conforms to Adobe's 2.0 conventions,
+ *
+ *	1) Marks the end of the prologue (only definitions) with %%EndProlog.
+ *
+ *	2) Brackets global initialization with %%BeginSetup and %%EndSetup comments
+ *	   which come after the prologue but before the first %Page: comment.
+ *
+ *	3) Starts each page with a %%Page: comment.
+ *
+ *	4) Marks the end of all the pages with a %%Trailer comment.
+ *
+ *	5) Obeys page independence.
+ *
+ * postreverse can handle documents that follow the 1.0 or 2.0 conventions, but has
+ * also been extended slightly so it works properly with the translators (primarily
+ * dpost) supplied with this package. The page independence requirement has been
+ * relaxed some. In particular definitions exported to the global environment from
+ * within a page should be bracketed by %%BeginGlobal and %%EndGlobal comments.
+ * postreverse pulls them out of each page and inserts them in the setup section
+ * of the document, immediately before it writes the %%EndProlog (for version 1.0)
+ * or %%EndSetup (for version 2.0) comments.
+ *
+ * In addition postreverse accepts documents that choose to mark the end of each
+ * page with a %%EndPage: comment, which from a translator's point of view is often
+ * a more natural approach. Both page boundary comments (ie. Page: and %%EndPage:)
+ * are also accepted, but be warned that everything between consecutive %%EndPage:
+ * and %%Page: comments will be ignored.
+ *
+ * So a document that will reverse properly with postreverse,
+ *
+ *	1) Marks the end of the prologue with %%EndProlog.
+ *
+ *	2) May have a %%BeginSetup/%%EndSetup comment pair before the first %%Page:
+ *	   comment that brackets any global initialization.
+ *
+ *	3) Marks the start of each page with a %%Page: comment, or the end of each
+ *	   page with a %%EndPage: comment. Both page boundary comments are allowed.
+ *
+ *	4) Marks the end of all the pages with a %%Trailer comment.
+ *
+ *	5) Obeys page independence or violates it to a rather limited extent and
+ *	   marks the violations with %%BeginGlobal and %%EndGlobal comments.
+ *
+ * If no file arguments are given postreverse copies stdin to a temporary file and
+ * then processes that file. That means the input is read three times (rather than
+ * two) whenever we handle stdin. That's expensive, and shouldn't be too difficult
+ * to fix, but I haven't gotten around to it yet.
+ *
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "comments.h"			/* PostScript file structuring comments */
+#include "gen.h"			/* general purpose definitions */
+#include "path.h"			/* for temporary directory */
+#include "ext.h"			/* external variable declarations */
+#include "postreverse.h"		/* a few special definitions */
+
+int	page = 1;			/* current page number */
+int	forms = 1;			/* forms per page in the input file */
+
+char	*temp_dir = TEMPDIR;		/* temp directory for copying stdin */
+
+Pages	pages[1000];			/* byte offsets for all pages */
+int	next_page = 0;			/* next page goes here */
+long	start;				/* starting offset for next page */
+long	endoff = -1;			/* offset where TRAILER was found */
+int	noreverse = FALSE;		/* don't reverse pages if TRUE */
+char	*endprolog = ENDPROLOG;		/* occasionally changed to ENDSETUP */
+
+double	version = 3.3;			/* of the input file */
+int	ignoreversion = FALSE;		/* ignore possible forms.ps problems */
+
+char	buf[2048];			/* line buffer for input file */
+
+FILE	*fp_in;				/* stuff is read from this file */
+FILE	*fp_out;			/* and written here */
+
+/*****************************************************************************/
+
+main(agc, agv)
+
+    int		agc;
+    char	*agv[];
+
+{
+
+/*
+ *
+ * A simple program that reverses the pages in specially formatted PostScript
+ * files. Will work with all the translators in this package, and should handle
+ * any document that conforms to Adobe's version 1.0 or 2.0 file structuring
+ * conventions. Only one input file is allowed, and it can either be a named (on
+ * the command line) file or stdin.
+ *
+ */
+
+    argc = agc;				/* other routines may want them */
+    argv = agv;
+
+    prog_name = argv[0];		/* just for error messages */
+
+    fp_in = stdin;
+    fp_out = stdout;
+
+    init_signals();			/* sets up interrupt handling */
+    options();				/* first get command line options */
+    arguments();			/* then process non-option arguments */
+    done();				/* and clean things up */
+
+    exit(x_stat);			/* not much could be wrong */
+
+}   /* End of main */
+
+/*****************************************************************************/
+
+init_signals()
+
+{
+
+/*
+ *
+ * Makes sure we handle interrupts properly.
+ *
+ */
+
+    if ( signal(SIGINT, interrupt) == SIG_IGN )  {
+	signal(SIGINT, SIG_IGN);
+	signal(SIGQUIT, SIG_IGN);
+	signal(SIGHUP, SIG_IGN);
+    } else {
+	signal(SIGHUP, interrupt);
+	signal(SIGQUIT, interrupt);
+    }   /* End else */
+
+    signal(SIGTERM, interrupt);
+
+}   /* End of init_signals */
+
+/*****************************************************************************/
+
+options()
+
+{
+
+    int		ch;			/* return value from getopt() */
+    char	*optnames = "n:o:rvT:DI";
+
+    extern char	*optarg;		/* used by getopt() */
+    extern int	optind;
+
+/*
+ *
+ * Reads and processes the command line options. The -r option (ie. the one that
+ * turns page reversal off) is really only useful if you want to take dpost output
+ * and produce a page independent output file. In that case global definitions
+ * made within pages and bracketed by %%BeginGlobal/%%EndGlobal comments will be
+ * moved into the prologue or setup section of the document.
+ *
+ */
+
+    while ( (ch = getopt(argc, argv, optnames)) != EOF )  {
+	switch ( ch )  {
+	    case 'n':			/* forms per page */
+		    if ( (forms = atoi(optarg)) <= 0 )
+			error(FATAL, "illegal forms request %s", optarg);
+		    break;
+
+	    case 'o':			/* output page list */
+		    out_list(optarg);
+		    break;
+
+	    case 'r':			/* don't reverse the pages */
+		    noreverse = TRUE;
+		    break;
+
+	    case 'v':			/* ignore possible forms.ps problems */
+		    ignoreversion = TRUE;
+		    break;
+
+	    case 'T':			/* temporary file directory */
+		    temp_dir = optarg;
+		    break;
+
+	    case 'D':			/* debug flag */
+		    debug = ON;
+		    break;
+
+	    case 'I':			/* ignore FATAL errors */
+		    ignore = ON;
+		    break;
+
+	    case '?':			/* don't understand the option */
+		    error(FATAL, "");
+		    break;
+
+	    default:			/* don't know what to do for ch */
+		    error(FATAL, "missing case for option %c\n", ch);
+		    break;
+	}   /* End switch */
+    }   /* End while */
+
+    argc -= optind;			/* get ready for non-option args */
+    argv += optind;
+
+}   /* End of options */
+
+/*****************************************************************************/
+
+arguments()
+
+{
+
+    char	*name;			/* name of the input file */
+
+/*
+ *
+ * postreverse only handles one input file at a time, so if there's more than one
+ * argument left when we get here we'll quit. If none remain we copy stdin to a
+ * temporary file and process that file.
+ *
+ */
+
+    if ( argc > 1 )			/* can't handle more than one file */
+	error(FATAL, "too many arguments");
+
+    if ( argc == 0 )			/* copy stdin to a temporary file */
+	name = copystdin();
+    else name = *argv;
+
+    if ( (fp_in = fopen(name, "r")) == NULL )
+	error(FATAL, "can't open %s", name);
+
+    reverse();
+
+}   /* End of arguments */
+
+/*****************************************************************************/
+
+done()
+
+{
+
+/*
+ *
+ * Cleans things up after we've finished reversing the pages in the input file.
+ * All that's really left to do is remove the temp file, provided we used one.
+ *
+ */
+
+    if ( temp_file != NULL )
+	unlink(temp_file);
+
+}   /* End of done */
+
+/*****************************************************************************/
+
+char *copystdin()
+
+{
+
+    int		fd_out;			/* for the temporary file */
+    int		fd_in;			/* for stdin */
+    int		count;			/* number of bytes put in buf[] */
+
+/*
+ *
+ * Copies stdin to a temporary file and returns the pathname of that file to the
+ * caller. It's an expensive way of doing things, because it means we end up
+ * reading the input file three times - rather than just twice. Could probably be
+ * fixed by creating the temporary file on the fly as we read the file the first
+ * time.
+ *
+ */
+
+    if ( (temp_file = tempnam(temp_dir, "post")) == NULL )
+	error(FATAL, "can't generate temp file name");
+
+    if ( (fd_out = creat(temp_file, 0660)) == -1 )
+	error(FATAL, "can't open %s", temp_file);
+
+    fd_in = fileno(stdin);
+
+    while ( (count = read(fd_in, buf, sizeof(buf))) > 0 )
+	if ( write(fd_out, buf, count) != count )
+	    error(FATAL, "error writing to %s", temp_file);
+
+    close(fd_out);
+
+    return(temp_file);
+
+}   /* End of copystdin */
+
+/*****************************************************************************/
+
+reverse()
+
+{
+
+/*
+ *
+ * Begins by looking for the ENDPROLOG comment in the input file. Everything up to
+ * that comment is copied to the output file. If the comment isn't found the entire
+ * input file is copied and moreprolog() returns FALSE. Otherwise readpages() reads
+ * the rest of the input file and remembers (in pages[]) where each page starts and
+ * ends. In addition everything bracketed by %%BeginGlobal and %%EndGlobal comments
+ * is immediately added to the new prologue (or setup section) and ends up being
+ * removed from the individual pages. When readpages() finds the TRAILER comment
+ * or gets to the end of the input file we go back to the pages[] array and use
+ * the saved offsets to write the pages out in reverse order. Finally everything
+ * from the TRAILER comment to the end of the input file is copied to the output
+ * file.
+ *
+ */
+
+    if ( moreprolog(ENDPROLOG) == TRUE )  {
+	readpages();
+	writepages();
+	trailer();
+    }	/* End if */
+
+}   /* End of reverse */
+
+/*****************************************************************************/
+
+moreprolog(str)
+
+    char	*str;			/* copy everything up to this string */
+
+{
+
+    int		len;			/* length of FORMSPERPAGE string */
+    int		vlen;			/* length of VERSION string */
+
+/*
+ *
+ * Looks for string *str at the start of a line and copies everything up to that
+ * string to the output file. If *str isn't found the entire input file will end
+ * up being copied to the output file and FALSE will be returned to the caller.
+ * The first call (made from reverse()) looks for ENDPROLOG. Any other call comes
+ * from readpages() and will be looking for the ENDSETUP comment.
+ * 
+ */
+
+    len = strlen(FORMSPERPAGE);
+    vlen = strlen(VERSION);
+
+    while ( fgets(buf, sizeof(buf), fp_in) != NULL )  {
+	if ( strcmp(buf, str) == 0 )
+	    return(TRUE);
+	else if ( strncmp(buf, FORMSPERPAGE, len) == 0 )
+	    forms = atoi(&buf[len+1]);
+	else if ( strncmp(buf, VERSION, vlen) == 0 )
+	    version = atof(&buf[vlen+1]);
+	fprintf(fp_out, "%s", buf);
+    }	/* End while */
+
+    return(FALSE);
+
+}   /* End of moreprolog */
+
+/*****************************************************************************/
+
+readpages()
+
+{
+
+    int		endpagelen;		/* length of ENDPAGE */
+    int		pagelen;		/* and PAGE strings */
+    int		sawendpage = TRUE;	/* ENDPAGE equivalent marked last page */
+    int		gotpage = FALSE;	/* TRUE disables BEGINSETUP stuff */
+
+/*
+ *
+ * Records starting and ending positions of the requested pages (usually all of
+ * them), puts global definitions in the prologue, and remembers where the TRAILER
+ * was found.
+ *
+ * Page boundaries are marked by the strings PAGE, ENDPAGE, or perhaps both.
+ * Application programs will normally find one or the other more convenient, so
+ * in most cases only one kind of page delimiter will be found in a particular
+ * document.
+ *
+ */
+
+    pages[0].start = ftell(fp_in);	/* first page starts after ENDPROLOG */
+    endprolog = ENDPROLOG;
+
+    endpagelen = strlen(ENDPAGE);
+    pagelen = strlen(PAGE);
+
+    while ( fgets(buf, sizeof(buf), fp_in) != NULL )
+	if ( buf[0] != '%' )
+	    continue;
+	else if ( strncmp(buf, ENDPAGE, endpagelen) == 0 )  {
+	    if ( in_olist(page++) == ON )  {
+		pages[next_page].empty = FALSE;
+		pages[next_page++].stop = ftell(fp_in);
+	    }	/* End if */
+	    pages[next_page].start = ftell(fp_in);
+	    sawendpage = TRUE;
+	    gotpage = TRUE;
+	} else if ( strncmp(buf, PAGE, pagelen) == 0 )  {
+	    if ( sawendpage == FALSE && in_olist(page++) == ON )  {
+		pages[next_page].empty = FALSE;
+		pages[next_page++].stop = ftell(fp_in) - strlen(buf);
+	    }	/* End if */
+	    pages[next_page].start = ftell(fp_in) - strlen(buf);
+	    sawendpage = FALSE;
+	    gotpage = TRUE;
+	} else if ( gotpage == FALSE && strcmp(buf, BEGINSETUP) == 0 )  {
+	    fprintf(fp_out, "%s", endprolog);
+	    fprintf(fp_out, "%s", BEGINSETUP);
+	    moreprolog(ENDSETUP);
+	    endprolog = ENDSETUP;
+	} else if ( strcmp(buf, BEGINGLOBAL) == 0 )  {
+	    moreprolog(ENDGLOBAL);
+	} else if ( strcmp(buf, TRAILER) == 0 )  {
+	    if ( sawendpage == FALSE )
+		pages[next_page++].stop = ftell(fp_in) - strlen(buf);
+	    endoff = ftell(fp_in);
+	    break;
+	}   /* End if */
+
+}   /* End of readpages */
+
+/*****************************************************************************/
+
+writepages()
+
+{
+
+    int		i, j, k;		/* loop indices */
+
+/*
+ *
+ * Goes through the pages[] array, usually from the bottom up, and writes out all
+ * the pages. Documents that print more than one form per page cause things to get
+ * a little more complicated. Each physical page has to have its subpages printed
+ * in the correct order, and we have to build a few dummy subpages for the last
+ * (and now first) sheet of paper, otherwise things will only occasionally work.
+ *
+ */
+
+    fprintf(fp_out, "%s", endprolog);
+
+    if ( noreverse == FALSE )		/* fill out the first page */
+	for ( i = (forms - next_page % forms) % forms; i > 0; i--, next_page++ )
+	    pages[next_page].empty = TRUE;
+    else forms = next_page;		/* turns reversal off in next loop */
+
+    for ( i = next_page - forms; i >= 0; i -= forms )
+	for ( j = i, k = 0; k < forms; j++, k++ )
+	    if ( pages[j].empty == TRUE ) {
+		if ( ignoreversion == TRUE || version > 3.1 ) {
+		    fprintf(fp_out, "%s 0 0\n", PAGE);
+		    fprintf(fp_out, "/saveobj save def\n");
+		    fprintf(fp_out, "showpage\n");
+		    fprintf(fp_out, "saveobj restore\n");
+		    fprintf(fp_out, "%s 0 0\n", ENDPAGE);
+		} else {
+		    fprintf(fp_out, "%s 0 0\n", PAGE);
+		    fprintf(fp_out, "save showpage restore\n");
+		    fprintf(fp_out, "%s 0 0\n", ENDPAGE);
+		}   /* End else */
+	    } else copypage(pages[j].start, pages[j].stop);
+
+}   /* End of writepages */
+
+/*****************************************************************************/
+
+copypage(start, stop)
+
+    long	start;			/* starting from this offset */
+    long	stop;			/* and ending here */
+
+{
+
+/*
+ *
+ * Copies the page beginning at offset start and ending at stop to the output
+ * file. Global definitions are skipped since they've already been added to the
+ * prologue.
+ *
+ */
+
+    fseek(fp_in, start, 0);
+
+    while ( ftell(fp_in) < stop && fgets(buf, sizeof(buf), fp_in) != NULL )
+	if ( buf[0] == '%' && strcmp(buf, BEGINGLOBAL) == 0 )
+	    while ( fgets(buf, sizeof(buf), fp_in) != NULL && strcmp(buf, ENDGLOBAL) != 0 ) ;
+	else fprintf(fp_out, "%s", buf);
+
+}   /* End of copypage */
+
+/*****************************************************************************/
+
+trailer()
+
+{
+
+/*
+ *
+ * Makes sure everything from the TRAILER string to EOF is copied to the output
+ * file.
+ *
+ */
+
+    if ( endoff > 0 )  {
+	fprintf(fp_out, "%s", TRAILER);
+	fseek(fp_in, endoff, 0);
+	while ( fgets(buf, sizeof(buf), fp_in) != NULL )
+	    fprintf(fp_out, "%s", buf);
+    }	/* End if */
+
+}   /* End of trailer */
+
+/*****************************************************************************/
+
diff --git a/src/cmd/postscript/postreverse/postreverse.h b/src/cmd/postscript/postreverse/postreverse.h
new file mode 100644
index 0000000..edae7a2
--- /dev/null
+++ b/src/cmd/postscript/postreverse/postreverse.h
@@ -0,0 +1,21 @@
+/*
+ *
+ * An array of type Pages is used to keep track of the starting and ending byte
+ * offsets for the pages we've been asked to print.
+ *
+ */
+
+typedef struct {
+	long	start;			/* page starts at this byte offset */
+	long	stop;			/* and ends here */
+	int	empty;			/* dummy page if TRUE */
+} Pages;
+
+/*
+ *
+ * Some of the non-integer functions in postreverse.c.
+ *
+ */
+
+char	*copystdin();
+
diff --git a/src/cmd/postscript/printfont/mkfile b/src/cmd/postscript/printfont/mkfile
new file mode 100644
index 0000000..8ddadb2
--- /dev/null
+++ b/src/cmd/postscript/printfont/mkfile
@@ -0,0 +1,22 @@
+</$objtype/mkfile
+
+<../config
+
+POSTBIN=/rc/bin
+
+all:V:	printfont
+
+install installall:V:	$POSTBIN/printfont $POSTLIB/printfont.ps
+
+clean nuke:V:
+	rm -f printfont
+
+$POSTBIN/printfont:	printfont
+	cp $prereq $target
+
+$POSTLIB/printfont.ps:	printfont.ps
+	cp $prereq $target
+
+printfont:	printfont.rc
+	sed 's?^POSTLIB=.*?POSTLIB='$POSTLIB'?' printfont.rc >printfont
+	chmod 775 printfont
diff --git a/src/cmd/postscript/printfont/printfont.ps b/src/cmd/postscript/printfont/printfont.ps
new file mode 100644
index 0000000..7a881a4
--- /dev/null
+++ b/src/cmd/postscript/printfont/printfont.ps
@@ -0,0 +1,321 @@
+%
+% Formatted font dump. Assumes all fonts include valid FontBBox arrays.
+%
+
+/#copies 1 store
+/aspectratio 1 def
+/landscape false def
+/magnification 1 def
+/margin 10 def
+/orientation 0 def
+/rotation 1 def
+/xoffset 0 def
+/yoffset 0 def
+
+/axescount 0 def
+/charwidth false def
+/graynotdef 0.85 def
+/hireslinewidth 0.2 def
+/longnames false def
+/maxsize 6.0 def
+/minsize 4.5 def
+/numbercell true def
+/radix 16 def
+/labelfont /Helvetica def
+/labelspace 36 def
+/zerocell 0 def
+
+/roundpage true def
+/useclippath true def
+/pagebbox [0 0 612 792] def
+
+/inch {72 mul} def
+/min {2 copy gt {exch} if pop} def
+/max {2 copy lt {exch} if pop} def
+
+/LLx {0 get} bind def
+/LLy {1 get} bind def
+/URx {2 get} bind def
+/URy {3 get} bind def
+/BBoxHeight {dup URy exch LLy sub} bind def
+/BBoxWidth {dup URx exch LLx sub} bind def
+
+/setup {
+	/graylevels [1 0 0] def
+	/scratchstring 512 string def
+	/Product statusdict begin /product where {pop product}{(Unknown)} ifelse end def
+	/Resolution 0 72 dtransform dup mul exch dup mul add sqrt cvi def
+	/Version /version where {pop version}{(???)} ifelse def
+
+	landscape {/orientation 90 orientation add def} if
+
+	pagedimensions
+	xcenter ycenter translate
+	orientation rotation mul rotate
+	width 2 div neg height 2 div translate
+	xoffset inch yoffset inch neg translate
+	margin dup neg translate
+	0 labelspace .75 mul neg translate
+	magnification dup aspectratio mul scale
+	0 0 transform round exch round exch itransform translate
+
+	currentdict /linewidth known not {
+		/linewidth Resolution 400 le {0}{hireslinewidth} ifelse def
+	} if
+} def
+
+/pagedimensions {
+	useclippath {
+		/pagebbox [clippath pathbbox newpath] def
+		roundpage currentdict /roundpagebbox known and {roundpagebbox} if
+	} if
+	pagebbox aload pop
+	4 -1 roll exch 4 1 roll 4 copy
+	landscape {4 2 roll} if
+	sub /width exch def
+	sub /height exch def
+	add 2 div /xcenter exch def
+	add 2 div /ycenter exch def
+} def
+
+/CharSetup {
+	/chcode exch def
+	/chname Encoding chcode get def
+	/chstring ( ) dup 0 chcode put def
+	/chknown true def
+
+	graylevels 0 1 put	% initial cell fill
+	graylevels 1 0 put	% cell text
+	graylevels 2 0 put	% cell border
+
+	FontDict /CharStrings known {
+		FontDict /CharStrings get chname known not {
+			/chknown false def
+			graylevels 0 0 put
+			graylevels 1 1 put
+		} if
+	} if
+
+	chname /.notdef eq {
+		/chknown false def
+		graylevels 0 graynotdef put
+		graylevels 1 graynotdef put
+	} if
+
+	/chwid chknown
+		{FontDict 1 scalefont setfont chstring stringwidth pop}
+		{0}
+	ifelse def
+} bind def
+
+/CellSetup {
+	/gridwidth width margin 2 mul sub def
+	/gridheight height labelspace sub margin 2 mul sub def
+	/cellwidth gridwidth radix div def
+	/cellheight gridheight Entries radix div ceiling div def
+
+	cellwidth cellheight dtransform truncate exch truncate exch idtransform
+	/cellheight exch def
+	/cellwidth exch def
+
+	labelfont findfont 1 scalefont setfont
+	/LabelBBox currentfont /FontBBox get TransformBBox def
+
+	LabelBBox 2 0 Encoding {
+		scratchstring cvs stringwidth pop
+		2 copy lt {exch} if
+		pop
+	} forall put
+
+	/CellLabelSize
+		cellheight .20 mul cellwidth .90 mul LabelBBox BestFit
+		minsize max
+		maxsize min
+	def
+	zerocell CellOrigin cellheight add neg exch neg exch translate
+} bind def
+
+/FontSetup {
+	FontName findfont 1 scalefont setfont
+	/BBox currentfont /FontBBox get TransformBBox def
+	/PointSize cellheight .5 mul cellwidth .8 mul BBox BestFit def
+	BBox {PointSize mul} forall BBox astore pop
+
+	/xorigin cellwidth BBox BBoxWidth sub 2 div BBox LLx sub def
+	/yorigin cellheight BBox BBoxHeight sub 2 div BBox LLy sub def
+} bind def
+
+/BestFit {
+	/bbox exch def
+	bbox BBoxWidth div exch
+	bbox BBoxHeight div min
+} bind def
+
+/TransformBBox {	% font bbox to user space
+	aload pop
+	currentfont /FontMatrix get dtransform 4 2 roll
+	currentfont /FontMatrix get dtransform 4 2 roll
+	4 array astore	% should build user space bbox if all zeros
+} bind def
+
+/CellOrigin {
+	dup
+	exch radix mod cellwidth mul
+	exch radix idiv 1 add neg cellheight mul
+} bind def
+
+/CellOutline {
+	newpath
+	CellOrigin moveto
+	cellwidth 0 rlineto
+	0 cellheight rlineto
+	cellwidth neg 0 rlineto
+	closepath
+} bind def
+
+/LabelCell {
+	gsave
+	chcode CellOrigin translate
+	linewidth .5 mul setlinewidth
+	labelfont findfont CellLabelSize scalefont setfont
+
+	numbercell {
+		cellwidth .025 mul cellheight .05 mul moveto
+		chcode radix scratchstring cvrs show
+	} if
+
+	charwidth chknown and {
+		/wid chwid 0.0005 add scratchstring cvs 0 5 getinterval def
+		cellwidth wid stringwidth pop 1.10 mul sub cellheight .05 mul moveto
+		wid show
+	} if
+
+	longnames chknown not or {
+		cellwidth .025 mul
+		cellheight LabelBBox URy CellLabelSize mul sub .05 sub moveto
+		Encoding chcode get scratchstring cvs show
+	} if
+
+	axescount 1 ge chknown and {	% gsave/grestore if not last
+		newpath
+		xorigin yorigin translate
+
+		BBox LLx 0 moveto	% baseline
+		BBox URx 0 lineto stroke
+
+		axescount 2 ge {	% vertical through current origin
+			0 BBox LLy moveto
+			0 BBox URy lineto stroke
+		} if
+
+		axescount 3 ge {	% vertical through next origin
+			chwid PointSize mul BBox LLy
+			dtransform round exch round exch idtransform moveto
+			0 BBox BBoxHeight rlineto stroke
+			%chwid PointSize mul BBox URy lineto stroke
+		} if
+	} if
+	grestore
+} bind def
+
+/PlaceChar {
+	FontName findfont PointSize scalefont setfont
+	chcode CellOrigin moveto
+	xorigin yorigin rmoveto
+	( ) dup 0 chcode put show
+} bind def
+
+/LabelPage {
+	labelfont findfont labelspace .75 mul .75 mul 18 min scalefont setfont
+	0 labelspace .75 mul .25 mul moveto
+	FontName scratchstring cvs show
+
+	labelfont findfont labelspace .25 mul .75 mul 9 min scalefont setfont
+	0 gridheight neg moveto
+	0 labelspace .25 mul .75 mul neg rmoveto
+	Product show ( Version ) show Version show
+	( \() show Resolution scratchstring cvs show (dpi\)) show
+
+	gridwidth gridheight neg moveto
+        0 labelspace .25 mul .75 mul neg rmoveto
+	(size=, ) stringwidth pop neg 0 rmoveto
+	PointSize cvi scratchstring cvs stringwidth pop neg 0 rmoveto
+	(gray=, ) stringwidth pop neg 0 rmoveto
+	graynotdef scratchstring cvs stringwidth pop neg 0 rmoveto
+	(linewidth=) stringwidth pop neg 0 rmoveto
+	linewidth scratchstring cvs stringwidth pop neg 0 rmoveto
+	(size=) show PointSize cvi scratchstring cvs show (, ) show
+	(gray=) show graynotdef scratchstring cvs show (, ) show
+	(linewidth=) show linewidth scratchstring cvs show
+} bind def
+
+%
+% Formatted dump of the encoded characters in a single font.
+%
+
+/PrintFont {
+	/saveobj save def
+	/FontName exch def
+	/FontDict FontName findfont def
+	/Encoding FontDict /Encoding get def
+	/Entries Encoding length def
+
+	CellSetup
+	FontSetup
+	LabelPage
+	zerocell 1 Entries 1 sub {
+		CharSetup
+		graylevels 0 get setgray
+		chcode CellOutline fill
+		graylevels 1 get setgray
+		LabelCell
+		PlaceChar
+		graylevels 2 get setgray
+		linewidth setlinewidth
+		chcode CellOutline stroke
+	} for
+	showpage
+	saveobj restore
+} bind def
+
+%
+% Dump of all ROM and disk fonts - in alphabetical order.
+%
+
+/AllFonts {
+	/AllFontNames FontDirectory maxlength array def
+	AllFontNames 0 0 put
+
+	FontDirectory {pop AllFontNames Insert} forall
+
+	/filenameforall where {
+		pop
+		(fonts/*)
+		{(fonts/) search pop pop pop AllFontNames Insert}
+		200 string
+		filenameforall
+	} if
+
+	1 1 AllFontNames 0 get {
+		AllFontNames exch get cvn PrintFont
+	} for
+} bind def
+
+/Insert {		% name in a sorted list
+	/List exch def
+	/Name exch 128 string cvs def
+
+	/Slot 1 def
+	List 0 get {
+		Name List Slot get le {exit} if
+		/Slot Slot 1 add def
+	} repeat
+
+	List 0 get -1 Slot {
+		dup List exch get
+		List 3 1 roll exch 1 add exch put
+	} for
+	List Slot Name put
+	List 0 List 0 get 1 add put
+} bind def
+
diff --git a/src/cmd/postscript/printfont/printfont.rc b/src/cmd/postscript/printfont/printfont.rc
new file mode 100644
index 0000000..266102f
--- /dev/null
+++ b/src/cmd/postscript/printfont/printfont.rc
@@ -0,0 +1,105 @@
+#!/bin/rc
+# Formatted dump of encoded characters in one or more PostScript fonts.
+# Arguments should be PostScript font names or the word all, which dumps
+# all ROM and disk based fonts.
+#
+
+POSTLIB=/sys/lib/postscript/prologues
+PROLOGUE=$POSTLIB/printfont.ps
+
+OPTIONS=''
+COPYFILE=''
+MODE=portrait
+FONTENCODING=Default
+
+NONCONFORMING='%!PS'
+ENDPROLOG='%%EndProlog'
+BEGINSETUP='%%BeginSetup'
+ENDSETUP='%%EndSetup'
+TRAILER='%%Trailer'
+
+SETUP=setup
+
+while (! ~ $#* 0 && ~ $1 -*) {
+	switch ($1) {
+	case -a;  shift; OPTIONS=$OPTIONS' /axescount $1 def'
+	case -a*; OPTIONS=$OPTIONS' /axescount '`{echo $1 | sed s/-a//}' def'
+
+	case -b;  shift; OPTIONS=$OPTIONS' /radix '$1' def'
+	case -b*; OPTIONS=$OPTIONS' /radix '`{echo $1 | sed s/-b//}' def'
+
+	case -c;  shift; OPTIONS=$OPTIONS' /#copies '$1' store'
+	case -c*; OPTIONS=$OPTIONS' /#copies '`{echo $1 | sed s/-c//}' store'
+
+	case -f;  shift; OPTIONS=$OPTIONS' /labelfont /'$1' def'
+	case -f*; OPTIONS=$OPTIONS' /labelfont /'`{echo $1 | sed s/-f//}' def'
+
+	case -g;  shift; OPTIONS=$OPTIONS' /graynotdef '$1' def'
+	case -g*; OPTIONS=$OPTIONS' /graynotdef '`{echo $1 | sed s/-g//}' def'
+
+	case -p;  shift; MODE=$1
+	case -p*; MODE=`{echo $1 | sed s/-p//}
+
+	case -q;  OPTIONS=$OPTIONS' /longnames false def /charwidth false def'
+
+	case -m;  shift; OPTIONS=$OPTIONS' /magnification '$1' def'
+	case -m*; OPTIONS=$OPTIONS' /magnification '`{echo $1 | sed s/-m//}' def'
+
+	case -v;  OPTIONS=$OPTIONS' /longnames true def /charwidth true def'
+
+	case -w;  shift; OPTIONS=$OPTIONS' /linewidth '$1' def'
+	case -w*; OPTIONS=$OPTIONS' /linewidth '`{echo $1 | sed s/-w//}' def'
+
+	case -x;  shift; OPTIONS=$OPTIONS' /xoffset '$1' def'
+	case -x*; OPTIONS=$OPTIONS' /xoffset '`{echo $1 | sed s/-x//}' def'
+
+	case -y;  shift; OPTIONS=$OPTIONS' /yoffset '$1' def'
+	case -y*; OPTIONS=$OPTIONS' /yoffset '`{echo $1 | sed s/-y//}' def'
+
+	case -z;  shift; OPTIONS=$OPTIONS' /zerocell '$1' def'
+	case -z*; OPTIONS=$OPTIONS' /zerocell '`{echo $1 | sed s/-z//}' def'
+
+	case -C;  shift; COPYFILE=$COPYFILE' '$1
+	case -C*; COPYFILE=$COPYFILE' '`{echo $1 | sed s/-C//}
+
+	case -E;  shift; FONTENCODING=$1
+	case -E*; FONTENCODING=`{echo $1 | sed s/-E//}
+
+	case -L;  shift; PROLOGUE=$1
+	case -L*; PROLOGUE=`{echo $1 | sed s/-L//}
+
+	case -*;  echo $0:' illegal option '$1 >[1=2]; exit 1
+	}
+	shift
+}
+
+switch ($MODE) {
+case l*; OPTIONS=$OPTIONS' /landscape true def'
+case *;	OPTIONS=$OPTIONS' /landscape false def'
+}
+
+echo $NONCONFORMING
+cat $PROLOGUE
+echo $ENDPROLOG
+echo $BEGINSETUP
+if (~ $#COPYFILE 0 || ~ $COPYFILE '') COPYFILE=/dev/null
+cat $COPYFILE
+echo $OPTIONS
+
+switch ($FONTENCODING) {
+case /*; cat $FONTENCODING
+case ?*; cat $POSTLIB^/$FONTENCODING^.enc >[2]/dev/null
+}
+
+echo $SETUP
+echo $ENDSETUP
+
+for (i) {
+	switch ($i) {
+	case all; echo AllFonts
+	case /*;  echo $i' PrintFont'
+	case ?*;  echo /$i' PrintFont'
+	}
+}
+
+echo $TRAILER
diff --git a/src/cmd/postscript/psencoding/.cvsignore b/src/cmd/postscript/psencoding/.cvsignore
new file mode 100644
index 0000000..7f44157
--- /dev/null
+++ b/src/cmd/postscript/psencoding/.cvsignore
@@ -0,0 +1 @@
+psencoding
diff --git a/src/cmd/postscript/psencoding/Latin1.enc b/src/cmd/postscript/psencoding/Latin1.enc
new file mode 100644
index 0000000..1e6e60b
--- /dev/null
+++ b/src/cmd/postscript/psencoding/Latin1.enc
@@ -0,0 +1,299 @@
+%
+% Encoding vector and redefinition of findfont for the ISO Latin1 standard.
+% The 18 characters missing from ROM based fonts on older printers are noted
+% below.
+%
+
+/ISOLatin1Encoding [
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/space
+	/exclam
+	/quotedbl
+	/numbersign
+	/dollar
+	/percent
+	/ampersand
+	/quoteright
+	/parenleft
+	/parenright
+	/asterisk
+	/plus
+	/comma
+	/minus
+	/period
+	/slash
+	/zero
+	/one
+	/two
+	/three
+	/four
+	/five
+	/six
+	/seven
+	/eight
+	/nine
+	/colon
+	/semicolon
+	/less
+	/equal
+	/greater
+	/question
+	/at
+	/A
+	/B
+	/C
+	/D
+	/E
+	/F
+	/G
+	/H
+	/I
+	/J
+	/K
+	/L
+	/M
+	/N
+	/O
+	/P
+	/Q
+	/R
+	/S
+	/T
+	/U
+	/V
+	/W
+	/X
+	/Y
+	/Z
+	/bracketleft
+	/backslash
+	/bracketright
+	/asciicircum
+	/underscore
+	/quoteleft
+	/a
+	/b
+	/c
+	/d
+	/e
+	/f
+	/g
+	/h
+	/i
+	/j
+	/k
+	/l
+	/m
+	/n
+	/o
+	/p
+	/q
+	/r
+	/s
+	/t
+	/u
+	/v
+	/w
+	/x
+	/y
+	/z
+	/braceleft
+	/bar
+	/braceright
+	/asciitilde
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/dotlessi
+	/grave
+	/acute
+	/circumflex
+	/tilde
+	/macron
+	/breve
+	/dotaccent
+	/dieresis
+	/.notdef
+	/ring
+	/cedilla
+	/.notdef
+	/hungarumlaut
+	/ogonek
+	/caron
+	/space
+	/exclamdown
+	/cent
+	/sterling
+	/currency
+	/yen
+	/brokenbar		% missing
+	/section
+	/dieresis
+	/copyright
+	/ordfeminine
+	/guillemotleft
+	/logicalnot
+	/hyphen
+	/registered
+	/macron
+	/degree			% missing
+	/plusminus		% missing
+	/twosuperior		% missing
+	/threesuperior		% missing
+	/acute
+	/mu			% missing
+	/paragraph
+	/periodcentered
+	/cedilla
+	/onesuperior		% missing
+	/ordmasculine
+	/guillemotright
+	/onequarter		% missing
+	/onehalf		% missing
+	/threequarters		% missing
+	/questiondown
+	/Agrave
+	/Aacute
+	/Acircumflex
+	/Atilde
+	/Adieresis
+	/Aring
+	/AE
+	/Ccedilla
+	/Egrave
+	/Eacute
+	/Ecircumflex
+	/Edieresis
+	/Igrave
+	/Iacute
+	/Icircumflex
+	/Idieresis
+	/Eth			% missing
+	/Ntilde
+	/Ograve
+	/Oacute
+	/Ocircumflex
+	/Otilde
+	/Odieresis
+	/multiply		% missing
+	/Oslash
+	/Ugrave
+	/Uacute
+	/Ucircumflex
+	/Udieresis
+	/Yacute			% missing
+	/Thorn			% missing
+	/germandbls
+	/agrave
+	/aacute
+	/acircumflex
+	/atilde
+	/adieresis
+	/aring
+	/ae
+	/ccedilla
+	/egrave
+	/eacute
+	/ecircumflex
+	/edieresis
+	/igrave
+	/iacute
+	/icircumflex
+	/idieresis
+	/eth			% missing
+	/ntilde
+	/ograve
+	/oacute
+	/ocircumflex
+	/otilde
+	/odieresis
+	/divide			% missing
+	/oslash
+	/ugrave
+	/uacute
+	/ucircumflex
+	/udieresis
+	/yacute			% missing
+	/thorn			% missing
+	/ydieresis
+] def
+
+/NewFontDirectory FontDirectory maxlength dict def
+
+%
+% Apparently no guarantee findfont is defined in systemdict so the obvious
+%
+%	systemdict /findfont get exec
+%
+% can generate an error. So far the only exception is a VT600 (version 48.0).
+%
+
+userdict /@RealFindfont known not {
+	userdict begin
+		/@RealFindfont systemdict begin /findfont load end def
+	end
+} if
+
+/findfont {
+	dup NewFontDirectory exch known not {
+		dup
+		%dup systemdict /findfont get exec	% not always in systemdict
+		dup userdict /@RealFindfont get exec
+		dup /Encoding get StandardEncoding eq {
+			dup length dict begin
+				{1 index /FID ne {def}{pop pop} ifelse} forall
+				/Encoding ISOLatin1Encoding def
+				currentdict
+			end
+			/DummyFontName exch definefont
+		} if
+		NewFontDirectory 3 1 roll put
+	} if
+	NewFontDirectory exch get
+} bind def
+
diff --git a/src/cmd/postscript/psencoding/UTF.enc b/src/cmd/postscript/psencoding/UTF.enc
new file mode 100644
index 0000000..234764e
--- /dev/null
+++ b/src/cmd/postscript/psencoding/UTF.enc
@@ -0,0 +1,332 @@
+%
+% Encoding vector, operator and procedure redefinitions for Plan 9 UTF
+% encoding. Prologues are expected to take steps to ensure operator
+% redefinitions given here are actually used. Current implementation
+% assumes UTF byte streams that represent ASCII or Latin1 text.
+%
+
+/UTFLatin1Encoding [
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/space
+	/exclam
+	/quotedbl
+	/numbersign
+	/dollar
+	/percent
+	/ampersand
+	/quoteright
+	/parenleft
+	/parenright
+	/asterisk
+	/plus
+	/comma
+	/minus
+	/period
+	/slash
+	/zero
+	/one
+	/two
+	/three
+	/four
+	/five
+	/six
+	/seven
+	/eight
+	/nine
+	/colon
+	/semicolon
+	/less
+	/equal
+	/greater
+	/question
+	/at
+	/A
+	/B
+	/C
+	/D
+	/E
+	/F
+	/G
+	/H
+	/I
+	/J
+	/K
+	/L
+	/M
+	/N
+	/O
+	/P
+	/Q
+	/R
+	/S
+	/T
+	/U
+	/V
+	/W
+	/X
+	/Y
+	/Z
+	/bracketleft
+	/backslash
+	/bracketright
+	/asciicircum
+	/underscore
+	/quoteleft
+	/a
+	/b
+	/c
+	/d
+	/e
+	/f
+	/g
+	/h
+	/i
+	/j
+	/k
+	/l
+	/m
+	/n
+	/o
+	/p
+	/q
+	/r
+	/s
+	/t
+	/u
+	/v
+	/w
+	/x
+	/y
+	/z
+	/braceleft
+	/bar
+	/braceright
+	/asciitilde
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/.notdef
+	/dotlessi
+	/grave
+	/acute
+	/circumflex
+	/tilde
+	/macron
+	/breve
+	/dotaccent
+	/dieresis
+	/.notdef
+	/ring
+	/cedilla
+	/.notdef
+	/hungarumlaut
+	/ogonek
+	/caron
+	/.notdef		% was space
+	/exclamdown
+	/cent
+	/sterling
+	/currency
+	/yen
+	/brokenbar
+	/section
+	/dieresis
+	/copyright
+	/ordfeminine
+	/guillemotleft
+	/logicalnot
+	/hyphen
+	/registered
+	/macron
+	/degree
+	/plusminus
+	/twosuperior
+	/threesuperior
+	/acute
+	/mu
+	/paragraph
+	/periodcentered
+	/cedilla
+	/onesuperior
+	/ordmasculine
+	/guillemotright
+	/onequarter
+	/onehalf
+	/threequarters
+	/questiondown
+	/Agrave
+	/Aacute
+	/Acircumflex
+	/Atilde
+	/Adieresis
+	/Aring
+	/AE
+	/Ccedilla
+	/Egrave
+	/Eacute
+	/Ecircumflex
+	/Edieresis
+	/Igrave
+	/Iacute
+	/Icircumflex
+	/Idieresis
+	/Eth
+	/Ntilde
+	/Ograve
+	/Oacute
+	/Ocircumflex
+	/Otilde
+	/Odieresis
+	/multiply
+	/Oslash
+	/Ugrave
+	/Uacute
+	/Ucircumflex
+	/Udieresis
+	/Yacute
+	/Thorn
+	/germandbls
+	/agrave
+	/aacute
+	/acircumflex
+	/atilde
+	/adieresis
+	/aring
+	/ae
+	/ccedilla
+	/egrave
+	/eacute
+	/ecircumflex
+	/edieresis
+	/igrave
+	/iacute
+	/icircumflex
+	/idieresis
+	/eth
+	/ntilde
+	/ograve
+	/oacute
+	/ocircumflex
+	/otilde
+	/odieresis
+	/divide
+	/oslash
+	/ugrave
+	/uacute
+	/ucircumflex
+	/udieresis
+	/yacute
+	/thorn
+	/ydieresis
+] def
+
+/NewFontDirectory FontDirectory maxlength dict def
+
+%
+% Apparently no guarantee findfont is defined in systemdict so the obvious
+%
+%	systemdict /findfont get exec
+%
+% can generate an error. So far the only exception is a VT600 (version 48.0).
+%
+
+userdict /@RealFindfont known not {
+	userdict begin
+		/@RealFindfont systemdict begin /findfont load end def
+	end
+} if
+
+/findfont {
+	dup NewFontDirectory exch known not {
+		dup
+		%dup systemdict /findfont get exec	% not always in systemdict
+		dup userdict /@RealFindfont get exec
+		dup /Encoding get StandardEncoding eq {
+			dup length 1 add dict begin
+				{1 index /FID ne {def}{pop pop} ifelse} forall
+				/Encoding UTFLatin1Encoding def
+				/Metrics 1 dict def
+				Metrics /.notdef 0 put
+				currentdict
+			end
+			/DummyFontName exch definefont
+		} if
+		NewFontDirectory 3 1 roll put
+	} if
+	NewFontDirectory exch get
+} bind def
+
+%
+% Assume A0, except for A0A0 which is replaced by 20A0, can be ignored.
+% Works with ASCII or Latin1 because A0 has been re-encoded as a zero
+% width non-printing character. 
+%
+
+/UTFstring {
+	dup {
+		(\240\240) search {
+			pop
+			0 16#20 put
+		}{pop exit} ifelse
+	} loop
+} bind def
+
+/ashow {mark 4 1 roll UTFstring //ashow cvx exec cleartomark} bind def
+/awidthshow {mark 7 1 roll UTFstring //awidthshow cvx exec cleartomark} bind def
+/show {mark exch UTFstring //show cvx exec cleartomark} bind def
+/stringwidth {UTFstring //stringwidth cvx exec} bind def
+/widthshow {mark 5 1 roll UTFstring //widthshow cvx exec cleartomark} bind def
+
+%
+% kshow is harder - stack can't change because of the procedure.
+%
+
+/kshow dup load type /operatortype eq
+	{{UTFstring kshow} bind}
+	{{UTFstring //kshow cvx exec} bind}
+ifelse def
+
diff --git a/src/cmd/postscript/psencoding/mkfile b/src/cmd/postscript/psencoding/mkfile
new file mode 100644
index 0000000..eaceebd
--- /dev/null
+++ b/src/cmd/postscript/psencoding/mkfile
@@ -0,0 +1,22 @@
+</$objtype/mkfile
+
+<../config
+
+POSTBIN=$ROOT/rc/bin/postscript
+
+all:V:	psencoding
+
+install installall:V:	$POSTBIN/psencoding $POSTLIB/Latin1.enc $POSTLIB/UTF.enc
+
+clean nuke:V:
+	rm -f psencoding
+
+$POSTBIN/psencoding:	psencoding
+	cp $prereq $target
+
+$POSTLIB/%.enc:	%.enc
+	cp $prereq $target
+
+psencoding:	psencoding.rc
+	sed 's?^POSTLIB=.*?POSTLIB='$POSTLIB'?' psencoding.rc >psencoding
+	chmod 775 psencoding
diff --git a/src/cmd/postscript/psencoding/psencoding.rc b/src/cmd/postscript/psencoding/psencoding.rc
new file mode 100644
index 0000000..c0b6aef
--- /dev/null
+++ b/src/cmd/postscript/psencoding/psencoding.rc
@@ -0,0 +1,39 @@
+#!/bin/rc
+# Trivial script for checking and setting the default PostScript font
+# encoding. Changing the default assumes you can write in $POSTLIB.
+# Available font encodings are files in $POSTLIB that end in .enc.
+# The default is $POSTLIB/Default.enc.
+#
+
+POSTLIB=/sys/lib/postscript/prologues
+DEFAULT=Default.enc
+CURRENTDEFAULT=Standard
+
+if (~ $#* 0) {
+	cd $POSTLIB
+	for (i in *.enc) {
+		if (test -f $i -a $i '!=' $DEFAULT) {
+			NAME=`{echo $i | sed s/\\.enc//}
+			if (cmp $i $DEFAULT >/dev/null >[2]/dev/null) {
+				CURRENTDEFAULT=$NAME
+			}
+			echo $NAME
+		}
+	}
+	echo Standard
+	echo Default'='$CURRENTDEFAULT
+}
+if not {
+	switch ($1) {
+	case Default
+		;
+	case Standard
+		rm -f $POSTLIB/$DEFAULT
+	case *
+		if (test -f $POSTLIB/$1.enc) {
+			rm -f $POSTLIB/$DEFAULT
+			cp $POSTLIB/$1.enc $POSTLIB/$DEFAULT
+		}
+		if not echo unrecognized encoding name $1 >[1=2]
+	}
+}
diff --git a/src/cmd/postscript/psfiles/Nroundpage.ps b/src/cmd/postscript/psfiles/Nroundpage.ps
new file mode 100644
index 0000000..44a67a6
--- /dev/null
+++ b/src/cmd/postscript/psfiles/Nroundpage.ps
@@ -0,0 +1,11 @@
+%
+% A version of roundpage.ps that assumes a symmetric clipping path. Thanks
+% to Matthijs Melchior for the suggestion.
+%
+
+/roundpagebbox {
+	pagebbox dup 0 get pagebbox 2 get add 2 exch put
+	pagebbox dup 1 get pagebbox 3 get add 3 exch put
+	pagebbox 0 0 put
+	pagebbox 1 0 put
+} bind def
diff --git a/src/cmd/postscript/psfiles/README b/src/cmd/postscript/psfiles/README
new file mode 100644
index 0000000..c1a7014
--- /dev/null
+++ b/src/cmd/postscript/psfiles/README
@@ -0,0 +1,11 @@
+PostScript files that go in $(POSTLIB). Several, like forms.ps, are
+used by most translators supplied in this package. Most PostScript
+files only used by a single translator (e.g. the prologue) have been 
+been moved into the appropriate source directory. Files that end in
+.enc support alternate character sets (e.g. ISO Latin 1 alphabet).
+The implementation is left open, but typically redefines findfont.
+That approach works because findfont is a procedure rather than an
+operator, so it's not affected by bind. Also can't depend on having
+a systemdict definition for findfont. It's in userdict on Version
+48.0 VT600s.
+
diff --git a/src/cmd/postscript/psfiles/aps.ps b/src/cmd/postscript/psfiles/aps.ps
new file mode 100644
index 0000000..9ba0d30
--- /dev/null
+++ b/src/cmd/postscript/psfiles/aps.ps
@@ -0,0 +1,127 @@
+%
+% Tune things up so Linotronic output looks more like the APS-5. Pull this file
+% into dpost output using the -C option. To get the best looking output run dpost
+% with the -e2 option and use special font files that look like the APS tables but
+% have character codes (ie. the fourth column in the width tables) appropriate for
+% PostScript fonts. Widths in these tables must be for APS fonts!
+%
+% Start with fat versions of the stroked Courier and Courier-Oblique fonts - from
+% Johnathan Shopiro.
+%
+
+/newdict /Courier findfont length dict def
+/Courier findfont {
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+newdict /StrokeWidth 65 put
+/Courier newdict definefont pop
+
+/newdict /Courier-Oblique findfont length dict def
+/Courier-Oblique findfont {
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+newdict /StrokeWidth 65 put
+/Courier-Oblique newdict definefont pop
+
+%
+% Scaled down versions of the Helvetica font family.
+%
+
+/newdict /Helvetica findfont length dict def
+/Helvetica findfont {
+	1 index /FontMatrix eq {.922 .922 matrix scale matrix concatmatrix} if
+
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+/Helvetica newdict definefont pop
+
+/newdict /Helvetica-Oblique findfont length dict def
+/Helvetica-Oblique findfont {
+	1 index /FontMatrix eq {.922 .922 matrix scale matrix concatmatrix} if
+
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+/Helvetica-Oblique newdict definefont pop
+
+/newdict /Helvetica-Bold findfont length dict def
+/Helvetica-Bold findfont {
+	1 index /FontMatrix eq {.922 .922 matrix scale matrix concatmatrix} if
+
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+/Helvetica-Bold newdict definefont pop
+
+/newdict /Helvetica-BoldOblique findfont length dict def
+/Helvetica-BoldOblique findfont {
+	1 index /FontMatrix eq {.922 .922 matrix scale matrix concatmatrix} if
+
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+/Helvetica-BoldOblique newdict definefont pop
+
+%
+% Scaled up versions of the Times font family.
+%
+
+/newdict /Times-Roman findfont length dict def
+/Times-Roman findfont {
+	1 index /FontMatrix eq {1.0225 1.0225 matrix scale matrix concatmatrix} if
+
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+/Times-Roman newdict definefont pop
+
+/newdict /Times-Italic findfont length dict def
+/Times-Italic findfont {
+	1 index /FontMatrix eq {1.0225 1.0225 matrix scale matrix concatmatrix} if
+
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+/Times-Italic newdict definefont pop
+
+/newdict /Times-Bold findfont length dict def
+/Times-Bold findfont {
+	1 index /FontMatrix eq {1.0225 1.0225 matrix scale matrix concatmatrix} if
+
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+/Times-Bold newdict definefont pop
+
+/newdict /Times-BoldItalic findfont length dict def
+/Times-BoldItalic findfont {
+	1 index /FontMatrix eq {1.0225 1.0225 matrix scale matrix concatmatrix} if
+
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+/Times-BoldItalic newdict definefont pop
+
diff --git a/src/cmd/postscript/psfiles/banner.ps b/src/cmd/postscript/psfiles/banner.ps
new file mode 100644
index 0000000..d563741
--- /dev/null
+++ b/src/cmd/postscript/psfiles/banner.ps
@@ -0,0 +1,40 @@
+%
+% Simple program to print a banner page
+%
+
+/banner {
+	/saveobj save def
+	erasepage initgraphics
+
+	/#copies 1 def
+	/inch {72 mul} bind def
+	/pagebbox [clippath pathbbox newpath] def
+
+	/font /Helvetica def
+	/size 20 def
+	/height pagebbox 3 get def
+	/width pagebbox 2 get .09 mul def
+
+	.92 setgray
+	pagebbox 0 get pagebbox 1 get moveto
+	width 0 rlineto 0 height rlineto width neg 0 rlineto closepath eofill
+	pagebbox 2 get pagebbox 1 get moveto
+	width neg 0 rlineto 0 height rlineto width 0 rlineto closepath eofill
+	0 setgray
+
+	font findfont size scalefont setfont
+	/linesp size size .15 mul add neg def
+	/tab (Destination) stringwidth pop 1.5 mul def
+	/nextline {0 0 moveto show tab 0 moveto show 0 linesp translate} def
+
+	pagebbox 0 get 1.5 width mul add pagebbox 3 get 2.0 width mul sub translate
+	(Bin)  nextline
+	(Name) nextline
+	(Owner) nextline
+	(File) nextline
+	(Account) nextline
+	(Destination) nextline
+	(Spooldate) nextline
+	showpage
+	saveobj restore
+} bind def
diff --git a/src/cmd/postscript/psfiles/baseline.ps b/src/cmd/postscript/psfiles/baseline.ps
new file mode 100644
index 0000000..470047c
--- /dev/null
+++ b/src/cmd/postscript/psfiles/baseline.ps
@@ -0,0 +1,156 @@
+%
+% Stuff used to draw or set text along a baseline specified by parametric equations
+% for x and y.
+%
+
+/left -1 def
+/center 0 def
+/right 1 def
+
+/baselinedict 50 dict def
+
+/newbaseline {
+	baselinedict begin
+		/g' exch bind def
+		/f' exch bind def
+		/g  exch bind def
+		/f  exch bind def
+
+		counttomark 2 eq {/hoffset exch def} if
+		/res exch def
+
+		/t 0 def
+		/s 0 def
+		/voffset false def
+		cleartomark
+	end
+} bind def
+
+/drawfunnytext {
+	baselinedict begin
+		/t exch def
+		/mode exch def
+		/str exch def
+
+		mode left eq {
+			/leftstring emptystring def
+			/rightstring str def
+		} if
+
+		mode right eq {
+			/leftstring str reversestring def
+			/rightstring emptystring def
+		} if
+
+		mode center eq {
+			str splitstring
+			/rightstring exch def
+			/leftstring exch reversestring def
+		} if
+
+		gsave currentpoint translate leftstring left t baselineshow grestore
+		gsave currentpoint translate rightstring right t baselineshow grestore
+
+		/t 0 def
+		/s 0 def
+		/voffset false def
+		cleartomark
+	end
+} bind def
+
+/setfunnytext {
+	baselinedict begin
+		/vpos exch def
+		/hpos exch def
+		/str  exch def
+
+		voffset vpos ne {
+			/voffset vpos def
+			/t 0 def
+			/s hoffset def
+		} if
+
+		gsave
+			hoffset voffset translate
+			0 0 moveto
+			/ds hpos s sub def
+			/dt ds t f' dup mul t g' dup mul add sqrt res mul div def
+			/s s ds add def
+			/t t dt add def
+			str right t baselineshow
+		grestore
+	end
+} bind def
+
+baselinedict begin
+
+/f  {} bind def
+/g  {pop 0} bind def
+/f' {pop 1} bind def
+/g' {pop 0} bind def
+
+/s 0 def
+/t 0 def
+/res 72 def
+
+/onecharstring ( ) def
+/emptystring () def
+
+/baselineshow {
+	/t exch def
+	/mode exch def
+	/str exch def
+
+	gsave
+		t f res mul t g res mul translate
+		0 0 moveto
+		t g' t f' atan rotate
+		{
+			mode right eq {pop} if
+			grestore gsave
+			onecharstring 0 3 -1 roll put onecharstring stringwidth pop
+			/ds exch mode mul def
+			/dt ds t f' dup mul t g' dup mul add sqrt res mul div def
+			/t t dt add def
+			/s s ds add def
+			t f res mul t g res mul translate
+			0 0 moveto
+			t g' t f' atan rotate
+			mode left eq {pop} if
+		} str kshow
+	grestore
+} bind def
+
+/reversestring {
+	/str1 exch def
+
+	/str2 str1 length string def
+	/i 0 def
+	/n str1 length 1 sub def
+
+	{
+		str1 n get str2 exch i exch put
+		/i i 1 add def
+		/n n 1 sub def
+		n 0 lt {exit} if
+	} loop
+	str2
+} bind def
+
+/splitstring {
+	/str1 exch def
+
+	/len str1 stringwidth pop def
+	/s 0 def
+	/n 0 def
+	str1 length {
+		str1 n get onecharstring exch 0 exch put
+		/s onecharstring stringwidth pop s add def
+		s len 2 div ge {exit} if
+		/n n 1 add def
+	} repeat
+	str1 0 n 1 add getinterval
+	str1 n str1 length n sub getinterval
+} bind def
+
+end
diff --git a/src/cmd/postscript/psfiles/color.ps b/src/cmd/postscript/psfiles/color.ps
new file mode 100644
index 0000000..e304cc3
--- /dev/null
+++ b/src/cmd/postscript/psfiles/color.ps
@@ -0,0 +1,65 @@
+%
+% Color and reverse video support for dpost. A call made to setcolor with two
+% arguments implies reverse video printing.
+%
+
+/rgb {setrgbcolor} bind def
+/hsb {sethsbcolor} bind def
+
+/colordict 50 dict dup begin
+	/red			{ 1 0 0 } def
+	/green			{ 0 1 0 } def
+	/blue			{ 0 0 1 } def
+	/cyan			{ 0 1 1 } def
+	/magenta		{ 1 0 1 } def
+	/yellow			{ 1 1 0 } def
+	/white			{ 1 1 1 } def
+	/black			{ 0 0 0 } def
+end def
+
+/setcolor {
+	counttomark 1 eq {
+		dup colordict exch known not {pop /black} if
+		colordict exch get exec setrgbcolor
+	} if
+	counttomark 2 eq {
+		/backcolor exch def
+		/textcolor exch def
+		colordict backcolor known not colordict textcolor known not or {
+			/backcolor colordict /black get def
+			/textcolor colordict /white get def
+		} if
+		/backcolor colordict backcolor get def
+		/textcolor colordict textcolor get def
+		/dY1 0 def
+		/dY2 0 def
+		textcolor exec setrgbcolor
+	} if
+} bind def
+
+/drawrvbox {
+	/x2 exch def
+	/x1 exch def
+
+	currentpoint dup
+	/y1 exch def
+	/y2 exch def pop
+
+	dY1 0 eq dY2 0 eq and {
+		currentfont /FontBBox get aload pop
+		currentfont /FontMatrix get dtransform /dY2 exch def pop
+		currentfont /FontMatrix get dtransform /dY1 exch def pop
+	} if
+
+	/y1 y1 dY1 add def
+	/y2 y2 dY2 add def
+
+	backcolor exec setrgbcolor
+	newpath
+	x1 y1 moveto
+	x2 y1 lineto
+	x2 y2 lineto
+	x1 y2 lineto
+	closepath fill
+	textcolor exec setrgbcolor
+} bind def
diff --git a/src/cmd/postscript/psfiles/fatcourier.ps b/src/cmd/postscript/psfiles/fatcourier.ps
new file mode 100644
index 0000000..11d7188
--- /dev/null
+++ b/src/cmd/postscript/psfiles/fatcourier.ps
@@ -0,0 +1,26 @@
+%
+% Fat versions of the stroked Courier and Courier-Oblique - from Johnathan Shopiro.
+% Can be selectively pulled in using the -C option that's available with all the
+% PostScript translators or permanently added to any of the prologues. Helps on
+% Linotronic typesetters, where Courier and Courier-Oblique are too light!
+%
+
+/newdict /Courier findfont length 1 add dict def
+/Courier findfont {
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+newdict /StrokeWidth 60 put
+/Courier newdict definefont pop
+
+/newdict /Courier-Oblique findfont length 1 add dict def
+/Courier-Oblique findfont {
+	1 index /FID ne
+		{newdict 3 1 roll put}
+		{pop pop}
+	ifelse
+} forall
+newdict /StrokeWidth 60 put
+/Courier-Oblique newdict definefont pop
diff --git a/src/cmd/postscript/psfiles/forms.ps b/src/cmd/postscript/psfiles/forms.ps
new file mode 100644
index 0000000..a96fcda
--- /dev/null
+++ b/src/cmd/postscript/psfiles/forms.ps
@@ -0,0 +1,213 @@
+%
+% Procedures that let you print any number of pages on each sheet of paper. It's
+% far from perfect and won't handle everything (eg. it's not recursive), but should
+% be good enough for now. Assumes the default page coordinate system has been set
+% up before setupforms is called. lastpage makes certain the last page is printed,
+% and should be called immediately after the %%Trailer comment.
+%
+% Three lines of code needed for page image clipping have been commented out for
+% now. It works, but can really slow things down on some versions of PostScript.
+% Uncomment them if you want to clip pages.
+%
+
+/setupforms {
+    /formsperpage exch def
+
+    /currentform 0 def
+    /slop 5 def
+    /min {2 copy gt {exch} if pop} def
+
+%
+% Save the current environment so the real showpage can be restored when we're all
+% done. Occasionally helps when a banner page is included with the job.
+%
+
+    /saveobj save def
+
+%
+% Number of rows and columns we'll need - may exchange them later.
+%
+
+    /columns formsperpage sqrt ceiling cvi def
+    /rows formsperpage columns div ceiling cvi def
+
+%
+% Slop leaves a little room around the edge so page images can be outlined and have
+% the borders show up. Distance is in default coordinates, so we need to figure out
+% how it maps into user coordinates.
+%
+
+    6 array defaultmatrix
+    6 array currentmatrix
+    6 array invertmatrix
+    6 array concatmatrix
+    /tempmatrix exch def
+
+    0 slop tempmatrix dtransform dup mul exch dup mul add sqrt
+    /slop exch def
+
+%
+% Determine how big the image area is, using the clipping path bounding box minus
+% a little and leave the coordinates of the lower left corner of the clipping path
+% on the stack. Also temporarily set the size of each page (ie. formheight and
+% formwidth) from the clipping path - just in case old software uses this stuff.
+% Only works for coordinate systems that have been rotated by a multiple of 90
+% degrees.
+%
+
+    newpath clippath pathbbox
+    2 index sub dup /formheight exch def slop 2 mul sub /pageheight exch def
+    2 index sub dup /formwidth exch def slop 2 mul sub /pagewidth exch def
+
+%
+% New translators all store the size of each page in default coordinates in the
+% pagebbox array and it can be different than the size determined by the clipping
+% path. If we can find pagebbox use it to set the real dimensions of each page.
+% Leaves the coordinates of the lower left corner on the stack, (either from
+% pagebbox or clippath) so four numbers are there when we're done.
+%
+
+    userdict /gotpagebbox known userdict /pagebbox known and {
+	newpath
+	pagebbox 0 get pagebbox 1 get tempmatrix transform moveto
+	pagebbox 0 get pagebbox 3 get tempmatrix transform lineto
+	pagebbox 2 get pagebbox 3 get tempmatrix transform lineto
+	pagebbox 2 get pagebbox 1 get tempmatrix transform lineto
+	closepath pathbbox
+	2 index sub /formheight exch def
+	2 index sub /formwidth exch def
+    } {2 copy} ifelse
+
+%
+% Top two numbers are the displacement from the job's origin to the lower left
+% corner of each page image when we finish setting up the new coordinate system.
+%
+
+    /ycorner exch def
+    /xcorner exch def
+
+%
+% The two numbers left on the stack are the coordinates of the lower left corner
+% of the clipping path. Go there and then up a bit so page images can be outlined.
+%
+
+    translate
+    slop slop translate
+
+%
+% If the page is wider than high we may be able to do better if we exchange rows
+% and columns. Won't make a difference in the current orientation or if rows and
+% columns are the same.
+%
+
+    pagewidth pageheight gt {
+	rows columns /rows exch def /columns exch def
+    } if
+
+%
+% Find the orientation and scaling that makes things as large as possible. More
+% than what's really needed. First calculation essentially finds the minimum of
+% 1/rows and 1/columns.
+%
+
+    pagewidth formwidth columns mul div pageheight formheight rows mul div min
+    pageheight formwidth columns mul div pagewidth formheight rows mul div min
+
+    2 copy lt {
+	rotation 1 eq {
+	    landscape {
+		0 pageheight translate
+		-90 rotate
+	    }{
+		pagewidth 0 translate
+		90 rotate
+	    } ifelse
+	}{
+	    landscape {
+		pagewidth 0 translate
+		90 rotate
+	    }{
+		0 pageheight translate
+		-90 rotate
+	    } ifelse
+	} ifelse
+	pagewidth pageheight /pagewidth exch def /pageheight exch def
+	exch
+    } if
+
+%
+% Second number from the top is the best choice. Scale so everything will fit on
+% the current page, go back to the original origin, and then get ready for the
+% first page - which goes in the upper left corner.
+%
+
+    pop dup dup scale
+    xcorner neg ycorner neg translate
+    0 rows 1 sub formheight mul translate
+
+%
+% Try to center everything on the page - scaling we used is on top of the stack.
+%
+
+    dup pagewidth exch div formwidth columns mul sub 2 div
+    exch pageheight exch div formheight rows mul sub 2 div translate
+
+%
+% Redefine showpage.
+%
+
+    /!PreForms~showpage~ /showpage load def		% save current showpage
+
+    /showpage {
+	saveobj restore
+%	initclip
+	formsperpage 1 gt {
+	    gsave .1 setlinewidth outlineform stroke grestore
+	} if
+	formwidth 0 translate
+	/currentform currentform 1 add def
+	currentform columns mod 0 eq {
+	    columns formwidth mul neg formheight neg translate
+	} if
+	currentform formsperpage mod 0 eq {
+	    gsave !PreForms~showpage~ grestore
+	    currentform columns mod formwidth mul neg
+	    formsperpage columns idiv formheight mul translate
+	    /currentform 0 def
+	} if
+%	outlineform clip newpath
+	/saveobj save def
+    } bind def
+
+    /outlineform {
+	newpath
+	xcorner ycorner moveto
+	formwidth 0 rlineto
+	0 formheight rlineto
+	formwidth neg 0 rlineto
+	closepath
+    } bind def
+
+    /lastpage {
+	formsperpage 1 gt {
+	    currentform 0 ne {
+		/saveobj save def
+		0 1 formsperpage currentform sub formsperpage mod {
+		    pop showpage
+		} for
+		saveobj restore
+	    } if
+	    saveobj restore
+	    saveobj restore
+	} if
+    } def
+
+%
+% Clip the first page image and save the environment we just set up, including
+% the redefined showpage.
+%
+
+%   outlineform clip
+    newpath
+    /saveobj save def
+} def
diff --git a/src/cmd/postscript/psfiles/mkfile b/src/cmd/postscript/psfiles/mkfile
new file mode 100644
index 0000000..ee75ec5
--- /dev/null
+++ b/src/cmd/postscript/psfiles/mkfile
@@ -0,0 +1,12 @@
+</$objtype/mkfile
+
+<../config
+
+all:VQ:
+	;
+
+install installall:V:
+	cp *.ps ps.* $POSTLIB
+
+clean nuke:VQ:
+	;
diff --git a/src/cmd/postscript/psfiles/ps.requests b/src/cmd/postscript/psfiles/ps.requests
new file mode 100644
index 0000000..59e2a57
--- /dev/null
+++ b/src/cmd/postscript/psfiles/ps.requests
@@ -0,0 +1,16 @@
+%
+% Keywords begin with an @ in the first column. The value follows on the next
+% line and includes everything up to next keyword line, except for comments
+% which are lines that begin with % in the first column.
+%
+
+@manualfeed
+	statusdict begin
+		/manualfeedtimeout 300 def
+		/manualfeed true def
+	end
+
+@ledgertray
+	statusdict begin
+		ledgertray
+	end
diff --git a/src/cmd/postscript/psfiles/roundpage.ps b/src/cmd/postscript/psfiles/roundpage.ps
new file mode 100644
index 0000000..68d2d44
--- /dev/null
+++ b/src/cmd/postscript/psfiles/roundpage.ps
@@ -0,0 +1,30 @@
+%
+% Tries to round clipping path dimensions, as stored in array pagebbox, so they
+% match one of the known sizes in the papersizes array. Lower left coordinates
+% are always set to 0.
+%
+
+/roundpagebbox {
+    7 dict begin
+	/papersizes [8.5 inch 11 inch 14 inch 17 inch] def
+
+	/mappapersize {
+		/val exch def
+		/slop .5 inch def
+		/diff slop def
+		/j 0 def
+		0 1 papersizes length 1 sub {
+			/i exch def
+			papersizes i get val sub abs
+			dup diff le {/diff exch def /j i def} {pop} ifelse
+		} for
+		diff slop lt {papersizes j get} {val} ifelse
+	} def
+
+	pagebbox 0 0 put
+	pagebbox 1 0 put
+	pagebbox dup 2 get mappapersize 2 exch put
+	pagebbox dup 3 get mappapersize 3 exch put
+    end
+} bind def
+
diff --git a/src/cmd/postscript/psfiles/shade.ps b/src/cmd/postscript/psfiles/shade.ps
new file mode 100644
index 0000000..47e3167
--- /dev/null
+++ b/src/cmd/postscript/psfiles/shade.ps
@@ -0,0 +1,52 @@
+%
+% Shading support - primarily for ASCII file translators.
+%
+
+/grays [0.98 0.9 0.75 0.6] def
+
+/setshade {
+	/level exch def
+	level 0 le {
+		/textgray 0 def
+		/backgray 1 def
+	}{
+		/backgray level grays length gt
+			{/textgray 1 def 0}
+			{/textgray 0 def grays level 1 sub get}
+		ifelse def
+	} ifelse
+	textgray setgray
+	/dY1 0 def
+	/dY2 0 def
+} bind def
+
+/drawrvbox {
+	/x2 exch charwidth mul def
+	/x1 exch charwidth mul def
+
+	x1 x2 lt {
+		dup		% expects y on top
+		/y1 exch linespace mul def
+		/y2 y1 def
+
+		dY1 0 eq dY2 0 eq and {
+			currentfont /FontBBox get aload pop
+			160 sub
+			currentfont /FontMatrix get dtransform /dY2 exch def pop
+			100 add
+			currentfont /FontMatrix get dtransform /dY1 exch def pop
+		} if
+
+		/y1 y1 dY1 add def
+		/y2 y2 dY2 add def
+
+		backgray setgray
+		newpath
+		x1 y1 moveto
+		x2 y1 lineto
+		x2 y2 lineto
+		x1 y2 lineto
+		closepath fill
+	} if
+	textgray setgray
+} bind def
diff --git a/src/cmd/postscript/psfiles/unbind.ps b/src/cmd/postscript/psfiles/unbind.ps
new file mode 100644
index 0000000..98e6283
--- /dev/null
+++ b/src/cmd/postscript/psfiles/unbind.ps
@@ -0,0 +1,28 @@
+%
+% Unbind the operators in an executable array or packedarray. Leaves the
+% unbound array or the original object on the stack.
+%
+
+/unbind {
+	0 index xcheck
+	1 index type /arraytype eq
+	2 index type /packedarraytype eq or and {
+		dup length array copy cvx
+		dup 0 exch {
+			dup type /operatortype eq {
+				(                          ) cvs cvn cvx
+			} if
+
+			0 index xcheck
+			1 index type /arraytype eq
+			2 index type /packedarraytype eq or and {
+				unbind
+			} if
+
+			3 copy put pop
+			1 add
+		} forall
+		pop
+	} if
+} def
+
diff --git a/src/cmd/postscript/tr2post/Bgetfield.c b/src/cmd/postscript/tr2post/Bgetfield.c
index 8922139..974fce6 100644
--- a/src/cmd/postscript/tr2post/Bgetfield.c
+++ b/src/cmd/postscript/tr2post/Bgetfield.c
@@ -4,9 +4,6 @@
 #include "../common/common.h"
 #include "tr2post.h"
 
-#undef isspace
-#define isspace bisspace
-
 int
 isspace(Rune r)
 {
@@ -14,7 +11,7 @@
 }
 
 int
-Bskipws(Biobuf *bp) {
+Bskipws(Biobufhdr *bp) {
 	int r;
 	char c[UTFmax];
 	int sindex = 0;
@@ -36,13 +33,15 @@
 
 int
 asc2dig(char c, int base) {
-	if (c >= '0' && c <= '9')
+	if (c >= '0' && c <= '9'){
 		if (base == 8 && c > '7') return(-1);
 		else return(c - '0');
+	}
 
-	if (base == 16)
+	if (base == 16){
 		if (c >= 'a' && c <= 'f') return(10 + c - 'a');
 		else if (c >= 'A' && c <= 'F') return(10 + c - 'A');
+	}
 
 	return(-1);
 }
@@ -55,7 +54,7 @@
  */
 
 int
-Bgetfield(Biobuf *bp, int type, void *thing, int size) {
+Bgetfield(Biobufhdr *bp, int type, void *thing, int size) {
 	int r;
 	Rune R;
 	char c[UTFmax];
diff --git a/src/cmd/postscript/tr2post/chartab.c b/src/cmd/postscript/tr2post/chartab.c
index 87ab556..89bf0ff 100644
--- a/src/cmd/postscript/tr2post/chartab.c
+++ b/src/cmd/postscript/tr2post/chartab.c
@@ -120,30 +120,31 @@
 	return(-1);
 }
 
-char postroffdirname[] = "#9/sys/lib/postscript/troff";		/* "/sys/lib/postscript/troff/"; */
-char troffmetricdirname[] = "#9/sys/lib/troff/font";	/* "/sys/lib/troff/font/devutf/"; */
+char postroffdirname[] = LIBDIR "/postscript/troff";		/* "/sys/lib/postscript/troff/"; */
+char troffmetricdirname[] = LIBDIR "/troff/font";	/* "/sys/lib/troff/font/devutf/"; */
 
 int
 readpsfontdesc(char *fontname, int trindex) {
 	static char *filename = 0;
 	Biobuf *bfd;
-	Biobuf *Bfd;
+	Biobufhdr *Bfd;
 	int warn = 0, errorflg = 0, line =1, rv;
 	int start, end, offset;
 	int startfont, endfont, startchar, endchar, i, pfid;
 	char psfontnam[128];
 	struct troffont *tp;
+/*	struct charent *cp[]; */
 
 	if (debug) Bprint(Bstderr, "readpsfontdesc(%s,%d)\n", fontname, trindex);
 	filename=galloc(filename, strlen(postroffdirname)+1+strlen(fontname)+1, "readpsfontdesc: cannot allocate memory\n");
 	sprint(filename, "%s/%s", postroffdirname, fontname);
 
-	bfd = Bopen(unsharp(filename), OREAD);
+	bfd = Bopen(filename, OREAD);
 	if (bfd == 0) {
 		error(WARNING, "cannot open file %s\n", filename);
 		return(0);
 	}
-	Bfd = bfd;
+	Bfd = bfd; /* &(bfd->Biobufhdr); */
 
 	do {
 		offset = 0;
@@ -211,7 +212,7 @@
 readtroffmetric(char *fontname, int trindex) {
 	static char *filename = 0;
 	Biobuf *bfd;
-	Biobuf *Bfd;
+	Biobufhdr *Bfd;
 	int warn = 0, errorflg = 0, line =1, rv;
 	struct troffont *tp;
 	struct charent **cp;
@@ -225,12 +226,12 @@
 	filename=galloc(filename, strlen(troffmetricdirname)+4+strlen(devname)+1+strlen(fontname)+1, "readtroffmetric():filename");
 	sprint(filename, "%s/dev%s/%s", troffmetricdirname, devname, fontname);
 
-	bfd = Bopen(unsharp(filename), OREAD);
+	bfd = Bopen(filename, OREAD);
 	if (bfd == 0) {
 		error(WARNING, "cannot open file %s\n", filename);
 		return(0);
 	}
-	Bfd = bfd;
+	Bfd = bfd; /* &(bfd->Biobufhdr); */
 	do {
 		/* deal with the few lines at the beginning of the
 		 * troff font metric files.
diff --git a/src/cmd/postscript/tr2post/conv.c b/src/cmd/postscript/tr2post/conv.c
index 4b7d97f..ebc1f43 100644
--- a/src/cmd/postscript/tr2post/conv.c
+++ b/src/cmd/postscript/tr2post/conv.c
@@ -5,14 +5,14 @@
 #include "tr2post.h"
 
 void
-conv(Biobuf *Bp) {
+conv(Biobufhdr *Bp) {
 	long c, n;
 	int r;
 	char special[10];
 	int save;
 
 	inputlineno = 1;
-	if (debug) Bprint(Bstderr, "conv(Biobuf *Bp=0x%x)\n", Bp);
+	if (debug) Bprint(Bstderr, "conv(Biobufhdr *Bp=0x%x)\n", Bp);
 	while ((r = Bgetrune(Bp)) >= 0) {
 /* Bprint(Bstderr, "r=<%c>,0x%x\n", r, r); */
 /*		Bflush(Bstderr); */
diff --git a/src/cmd/postscript/tr2post/devcntl.c b/src/cmd/postscript/tr2post/devcntl.c
index 8b438f7..2566229 100644
--- a/src/cmd/postscript/tr2post/devcntl.c
+++ b/src/cmd/postscript/tr2post/devcntl.c
@@ -16,11 +16,11 @@
 
 /* I won't need this if getfields can replace sscanf
 
-extern void picture(Biobuf *);
+extern void picture(Biobufhdr *);
 extern void notavail(char *);
 
 void
-PSInclude(Biobuf *inp) {
+PSInclude(Biobufhdr *inp) {
 	char buf[256];
 
 	Bgetfield(inp, 's', buf, 256);
@@ -51,7 +51,7 @@
 */
 
 void
-devcntl(Biobuf *inp) {
+devcntl(Biobufhdr *inp) {
 
 	char cmd[50], buf[256], str[MAXTOKENSIZE], *line;
 	int c, n, linelen;
diff --git a/src/cmd/postscript/tr2post/draw.c b/src/cmd/postscript/tr2post/draw.c
index 575ec88..0cb368a 100644
--- a/src/cmd/postscript/tr2post/draw.c
+++ b/src/cmd/postscript/tr2post/draw.c
@@ -13,7 +13,7 @@
 }
 
 void
-drawspline(Biobuf *Bp, int flag) {	/* flag!=1 connect end points */
+drawspline(Biobufhdr *Bp, int flag) {	/* flag!=1 connect end points */
 	int x[100], y[100];
 	int i, N;
 /*
@@ -96,7 +96,7 @@
 }
 
 void
-draw(Biobuf *Bp) {
+draw(Biobufhdr *Bp) {
 
 	int r, x1, y1, x2, y2, i;
 	int d1, d2;
diff --git a/src/cmd/postscript/tr2post/pictures.c b/src/cmd/postscript/tr2post/pictures.c
index a20b7ad..8d758cb 100644
--- a/src/cmd/postscript/tr2post/pictures.c
+++ b/src/cmd/postscript/tr2post/pictures.c
@@ -50,8 +50,8 @@
 /* #include "ext.h" */
 
 Biobuf	*bfp_pic = NULL;
-Biobuf	*Bfp_pic;
-Biobuf	*picopen(char *);
+Biobufhdr	*Bfp_pic;
+Biobufhdr	*picopen(char *);
 
 #define MAXGETFIELDS	16
 char *fields[MAXGETFIELDS];
@@ -63,7 +63,7 @@
 /*****************************************************************************/
 
 void
-picture(Biobuf *inp, char *buf) {
+picture(Biobufhdr *inp, char *buf) {
 	int	poffset;		/* page offset */
 	int	indent;		/* indent */
 	int	length;		/* line length  */
@@ -80,7 +80,7 @@
 	double	adjx = 0.5;	/* left-right adjustment */
 	double	adjy = 0.5;	/* top-bottom adjustment */
 	double	rot = 0;	/* rotation in clockwise degrees */
-	Biobuf	*fp_in;	/* for *name */
+	Biobufhdr	*fp_in;	/* for *name */
 	int	i;			/* loop index */
 
 /*
@@ -195,18 +195,18 @@
  * open file *path and return the resulting file pointer to the caller.
  *
  */
-Biobuf *
+Biobufhdr *
 picopen(char *path) {
 /*	char	name[100];	/* pathnames */
 /*	long	pos;			/* current position */
 /*	long	total;			/* and sizes - from *fp_pic */
 	Biobuf *bfp;
-	Biobuf	*Bfp;		/* and pointer for the new temp file */
+	Biobufhdr	*Bfp;		/* and pointer for the new temp file */
 
 
 	if ((bfp = Bopen(path, OREAD)) == 0)
 		error(FATAL, "can't open %s\n", path);
-	Bfp = bfp;
+	Bfp = bfp; /* &(bfp->Biobufhdr); */
 	return(Bfp);
 #ifdef UNDEF
 	if (Bfp_pic != NULL) {
@@ -219,7 +219,7 @@
 					error(FATAL, "can't generate temp file name");
 				if ( (bfp = Bopen(pictmpname, ORDWR)) == NULL )
 					error(FATAL, "can't open %s", pictmpname);
-				Bfp = bfp;
+				Bfp = &(bfp->Biobufhdr);
 				piccopy(Bfp_pic, Bfp, total);
 				Bseek(Bfp, 0L, 0);
 				return(Bfp);
@@ -230,7 +230,7 @@
 	if ((bfp = Bopen(path, OREAD)) == 0)
 		Bfp = 0;
 	else
-		Bfp = bfp;
+		Bfp = &(bfp->Biobufhdr);
 	return(Bfp);
 #endif
 }
@@ -249,7 +249,7 @@
 
 #ifdef UNDEF
 void
-inlinepic(Biobuf *Bfp, char *buf) {
+inlinepic(Biobufhdr *Bfp, char *buf) {
 	char	name[100];		/* picture file pathname */
 	long	total;			/* and size - both from *buf */
 
@@ -285,7 +285,7 @@
 /*	*fp_out;	and output file pointers */
 /*	total;		number of bytes to be copied */
 void
-piccopy(Biobuf *Bfp_in, Biobuf *Bfp_out, long total) {
+piccopy(Biobufhdr *Bfp_in, Biobufhdr *Bfp_out, long total) {
 	long i;
 
 	for (i = 0; i < total; i++)
diff --git a/src/cmd/postscript/tr2post/ps_include.c b/src/cmd/postscript/tr2post/ps_include.c
index af30ff2..27d020a 100644
--- a/src/cmd/postscript/tr2post/ps_include.c
+++ b/src/cmd/postscript/tr2post/ps_include.c
@@ -11,8 +11,8 @@
 typedef struct {long start, end;} Section;
 static char *buf;
 
-static void
-copy(Biobuf *fin, Biobuf *fout, Section *s) {
+static
+copy(Biobufhdr *fin, Biobufhdr *fout, Section *s) {
 	int cond;
 	if (s->end <= s->start)
 		return;
@@ -57,7 +57,7 @@
 /*	rot;			/* rotation - in clockwise degrees */
 
 void
-ps_include(Biobuf *fin, Biobuf *fout, int page_no, int whiteout,
+ps_include(Biobufhdr *fin, Biobufhdr *fout, int page_no, int whiteout,
 	int outline, int scaleboth, double cx, double cy, double sx, double sy,
 	double ax, double ay, double rot) {
 	char		**strp;
diff --git a/src/cmd/postscript/tr2post/readDESC.c b/src/cmd/postscript/tr2post/readDESC.c
index 03b8b64..4dbc193 100644
--- a/src/cmd/postscript/tr2post/readDESC.c
+++ b/src/cmd/postscript/tr2post/readDESC.c
@@ -44,19 +44,19 @@
 	char *descnameformat = "%s/dev%s/DESC";
 	char *descfilename = 0;
 	Biobuf *bfd;
-	Biobuf *Bfd;
+	Biobufhdr *Bfd;
 	int i, state = -1;
 	int fontindex = 0;
 
 	if (debug) Bprint(Bstderr, "readDESC()\n");
 	descfilename = galloc(descfilename, strlen(descnameformat)+strlen(FONTDIR)
-		+strlen(devname)+1, "readdesc");
+		+strlen(devname), "readdesc");
 	sprint(descfilename, descnameformat, FONTDIR, devname);
-	if ((bfd = Bopen(unsharp(descfilename), OREAD)) == 0) {
+	if ((bfd = Bopen(descfilename, OREAD)) == 0) {
 		error(WARNING, "cannot open file %s\n", descfilename);
 		return(0);
 	}
-	Bfd = bfd;
+	Bfd = bfd; /* &(bfd->Biobufhdr); */
 
 	while (Bgetfield(Bfd, 's', token, MAXTOKENSIZE) > 0) {
 		for (i=0; i<NDESCTOKS; i++) {
diff --git a/src/cmd/postscript/tr2post/tr2post.c b/src/cmd/postscript/tr2post/tr2post.c
index d60e0c7..acfe604 100644
--- a/src/cmd/postscript/tr2post/tr2post.c
+++ b/src/cmd/postscript/tr2post/tr2post.c
@@ -23,7 +23,7 @@
 Biobuf *Bstdin, *Bstdout, *Bstderr;
 int debug = 0;
 
-char tmpfilename[MAXTOKENSIZE];
+char tmpfilename[MAXPATHLEN+1];
 char copybuf[BUFSIZ];
 
 
@@ -41,20 +41,20 @@
 	Bprint(Bstdout, "%s %s\n", PAGES, ATEND);
 	Bprint(Bstdout, "%s", ENDCOMMENTS);
 
-	if (cat(unsharp(DPOST))) {
+	if (cat(DPOST)) {
 		Bprint(Bstderr, "can't read %s\n", DPOST);
 		exits("dpost prologue");
 	}
 
 	if (drawflag) {
-		if (cat(unsharp(DRAW))) {
+		if (cat(DRAW)) {
 			Bprint(Bstderr, "can't read %s\n", DRAW);
 			exits("draw prologue");
 		}
 	}
 
 	if (DOROUND)
-		cat(unsharp(ROUNDPAGE));
+		cat(ROUNDPAGE);
 
 	Bprint(Bstdout, "%s", ENDPROLOG);
 	Bprint(Bstdout, "%s", BEGINSETUP);
@@ -70,19 +70,19 @@
 	if (pointsize != 10) Bprint(Bstdout, "/pointsize %d def\n", pointsize);
 	if (xoffset != .25) Bprint(Bstdout, "/xoffset %g def\n", xoffset);
 	if (yoffset != .25) Bprint(Bstdout, "/yoffset %g def\n", yoffset);
-	cat(unsharp(ENCODINGDIR"/Latin1.enc"));
+	cat(ENCODINGDIR"/Latin1.enc");
 	if (passthrough != 0) Bprint(Bstdout, "%s\n", passthrough);
 
 	Bprint(Bstdout, "setup\n");
 	if (formsperpage > 1) {
-		cat(unsharp(FORMFILE));
+		cat(FORMFILE);
 		Bprint(Bstdout, "%d setupforms \n", formsperpage);
 	}
 /* output Build character info from charlib if necessary. */
 
 	for (i=0; i<build_char_cnt; i++) {
 		sprint(charlibname, "%s/%s", CHARLIB, build_char_list[i]->name);
-		if (cat(unsharp(charlibname)))
+		if (cat(charlibname))
 		Bprint(Bstderr, "cannot open %s\n", charlibname);
 	}
 
@@ -95,24 +95,26 @@
 }
 
 main(int argc, char *argv[]) {
+	Biobuf btmp;
 	Biobuf *binp;
-	Biobuf *Binp;
-	int i, tot, ifd;
+	Biobufhdr *Binp;
+	int i, tot, ifd, fd;
 	char *t;
 
 	programname = argv[0];
 	if (Binit(&bstderr, 2, OWRITE) == Beof) {
 		exits("Binit");
 	}
-	Bstderr = &bstderr;
+	Bstderr = &bstderr;  /* &bstderr.Biobufhdr; */
 
-	tmpnam(tmpfilename);
-	if ((bstdout=Bopen(tmpfilename, OWRITE)) == 0) {
+	bstdout = &btmp;
+	fd = safe_tmpnam(tmpfilename);
+	if ((Binit(bstdout, fd, OWRITE)) == Beof) {
 		Bprint(Bstderr, "cannot open temporary file %s\n", tmpfilename);
 		exits("Bopen");
 	}
 	atexit(cleanup);
-	Bstdout = bstdout;
+	Bstdout = bstdout; /* &bstdout->Biobufhdr; */
 	
 	ARGBEGIN{
 		case 'a':			/* aspect ratio */
@@ -169,7 +171,7 @@
 			Bprint(Bstderr, "Binit of <stdin> failed.\n");
 			exits("Binit");
 		}
-		Binp = binp;
+		Binp = binp; /* &(binp->Biobufhdr); */
 		if (debug) Bprint(Bstderr, "using standard input\n");
 		conv(Binp);
 		Bterm(Binp);
@@ -179,7 +181,7 @@
 			Bprint(Bstderr, "cannot open file %s\n", argv[i]);
 			continue;
 		}
-		Binp = binp;
+		Binp = binp; /* &(binp->Biobufhdr); */
 		inputfilename = argv[i];
 		conv(Binp);
 		Bterm(Binp);
@@ -196,7 +198,7 @@
 		Bprint(Bstderr, "Binit of <stdout> failed.\n");
 		exits("Binit");
 	}
-	Bstdout = bstdout;
+	Bstdout = bstdout; /* &(bstdout->Biobufhdr); */
 	prologues();
 	Bflush(Bstdout);
 	tot = 0; i = 0;
diff --git a/src/cmd/postscript/tr2post/tr2post.h b/src/cmd/postscript/tr2post/tr2post.h
index b07e0b1..68299cc 100644
--- a/src/cmd/postscript/tr2post/tr2post.h
+++ b/src/cmd/postscript/tr2post/tr2post.h
@@ -1,6 +1,9 @@
 #define MAXSPECHARS 	512
 #define MAXTOKENSIZE	128
-#define CHARLIB	"#9/sys/lib/troff/font/devutf/charlib"
+#define CHARLIB	FONTDIR "/devutf/charlib"
+
+/* devname clashes with libc on *BSD */
+#define devname		troff_devname
 
 extern int debug;
 extern int fontsize;
diff --git a/src/cmd/postscript/tr2post/utils.c b/src/cmd/postscript/tr2post/utils.c
index 8f58ea4..e9979ff 100644
--- a/src/cmd/postscript/tr2post/utils.c
+++ b/src/cmd/postscript/tr2post/utils.c
@@ -250,7 +250,7 @@
 }
 
 void
-graphfunc(Biobuf *bp) {
+graphfunc(Biobufhdr *bp) {
 }
 
 long