|
|
1.1 ! root 1: .so ../ADM/mac ! 2: .XX lp 603 "A Guide to the Lp Printer Spooler" ! 3: .nr dP 1 ! 4: .nr dV 1.5p ! 5: .ND ! 6: .TL ! 7: A Guide to the Lp ! 8: Printer Spooler ! 9: .AU ! 10: P. Glick ! 11: .AI ! 12: AT&T Bell Laboratories ! 13: Murray Hill, New Jersey 07974 ! 14: .AB ! 15: .PP ! 16: .I Lp ! 17: is a collection of programs used to provide an easy-to-use ! 18: interface for printing a variety of document types on a variety ! 19: of printers. ! 20: .I Lp ! 21: is meant to be the glue that connects various document language ! 22: translators and printer communication programs together so that ! 23: the users may have a consistent view of printers. ! 24: Most of the glue ! 25: is shell script, which can be easily modified. ! 26: The user need not ! 27: specify options to get sensible output in most cases. ! 28: .I Lp ! 29: is described here ! 30: so that others may make additions and changes. ! 31: Only the shell scripts, or glue, are described here. ! 32: .AE ! 33: .2C ! 34: .NH ! 35: Introduction ! 36: .PP ! 37: .I Lp ! 38: is used to format and print data on a variety of output devices. ! 39: The need for ! 40: .I lp ! 41: was rooted in the inability of other printer spoolers to do simple ! 42: tasks without a great deal of user specification of options. ! 43: At the time ! 44: .I lp ! 45: was written, there were several printer ! 46: languages, such as ImPress and P\s-2OST\s+2S\s-2CRIPT\s+2 and ! 47: an internally developed printer that would accept ! 48: .I troff ! 49: output. ! 50: A great deal of what underlies ! 51: .I lp ! 52: is taken from other systems. ! 53: The important features of this system are that most of the programs ! 54: are easily modified shell scripts and the user need not ! 55: fuss with the large amount of underlying software developed by others. ! 56: .I Lp ! 57: runs under several flavors of the ! 58: .UX ! 59: Operating System ! 60: and uses both Datakit and Ethernet to transport data between machines. ! 61: .PP ! 62: Text, graphics, and formatted text files are appropriately processed and ! 63: placed into a spool directory from which they are taken to be printed. ! 64: Additional functions include checking the status of a printer queue ! 65: and removing jobs from the printer queue. ! 66: .PP ! 67: All files associated with ! 68: .I lp ! 69: reside in the spool directory ! 70: (usually \f(CW/usr/spool/lp\fP), ! 71: except for the ! 72: .I lp ! 73: command itself which usually resides in \f(CW/usr/bin\fP. ! 74: The spool directory is defined within the ! 75: .I lp ! 76: command by the shell variable \f(CWLPSPOOL\fP. ! 77: In the remainder of this document, file names may be specified ! 78: with this shell variable as their root. ! 79: .NH ! 80: Usage ! 81: .PP ! 82: .I Lp ! 83: requires that an output device be specified ! 84: before it will process input. ! 85: This can be done in any of three ways described here in increasing order ! 86: of precedence. ! 87: .SP .5 ! 88: .TA 5 ! 89: \(em The file ! 90: .CW $LPSPOOL/defdevice ! 91: may contain the name of a default output device. ! 92: This may not be practical for environments where ! 93: there are many printers ! 94: and the default device need not be specified. ! 95: .SP .5 ! 96: \(em The user's environment variable ! 97: .CW LPDEST ! 98: may be set to the name of the device to be used. ! 99: This is often a more practical solution when there are several printers ! 100: available. ! 101: This overrides a ! 102: .CW defdevice ! 103: specification. ! 104: .SP .5 ! 105: \(em The ! 106: .CW "-d printer" ! 107: option to the ! 108: .I lp ! 109: command specifies ! 110: .I printer ! 111: as the device to which output should be directed, overriding the ! 112: previous two specifications. ! 113: .PP ! 114: If ! 115: .I printer ! 116: is ! 117: .CW ? , ! 118: a list of printers and other information in the ! 119: .CW devices ! 120: file is printed, as shown in Figure 1. ! 121: .1C ! 122: .KF ! 123: .P1 20n ! 124: $ lp -d"?" ! 125: device location host class ! 126: dp 2C-504 nj/astro/coma post300+reverse ! 127: imagen1 st8_fl1 nj/phone/sid imagen/2.2+reverse ! 128: po 2C-579 nj/astro/pipe dumb ! 129: ps2c364 2C-364 nj/phone/sid post300+reverse ! 130: ps71 2D-154 nj/phone/gauss post300+reverse ! 131: ps83 st8_fl3 nj/phone/gauss post300+reverse ! 132: psu 2C-501 nj/astro/coma post300+reverse ! 133: . ! 134: . ! 135: . ! 136: $ ! 137: .P2 ! 138: .ce ! 139: \fBFigure 1.\fR Sample listing of installed printers. ! 140: .KE ! 141: .SP ! 142: .2C ! 143: .PP ! 144: Normal ! 145: .I troff ! 146: output can be printed with ! 147: .P1 ! 148: $ troff -ms lp.ms | lp -ddp ! 149: .P2 ! 150: .NE 3 ! 151: LaTex (and analogously Tex) documents are printed in two steps: ! 152: .P1 ! 153: $ latex lp.tex ! 154: . ! 155: . ! 156: $ lp -dpsu lp.dvi ! 157: . ! 158: . ! 159: $ ! 160: .P2 ! 161: LaTeX ! 162: produces a `.dvi' file and ! 163: does not permit the use of a pipe ! 164: connection to the standard input of ! 165: .I lp . ! 166: In both these cases I have explicitly specified a destination ! 167: because my ! 168: .CW LPDEST ! 169: variable is set to a printer near my office, which I use infrequently. ! 170: Although this doesn't make a great deal of sense, it is useful for ! 171: the purpose of these examples. ! 172: .PP ! 173: To look at the status and queue of a device: ! 174: .P1 0 ! 175: $ lp -dpsu -q ! 176: status: ! 177: %%[ status: idle ]%% ! 178: sending file psu/29436.1 ! 179: %%[ status: busy; source: serial 25 ]%% ! 180: ! 181: queue on nj/astro/coma: ! 182: job user try size ! 183: gauss29436.1 pg 0 17454 ! 184: coma17565.1 ches 1 49995 ! 185: $ ! 186: .P2 ! 187: This command prints the status and queue on the local ! 188: and remote hosts. ! 189: The format of the status and queue printout is up to the administrator. ! 190: .PP ! 191: The job started above can be killed as follows ! 192: (where the output is too long for the column, it has been folded at the \*(cr): ! 193: .P1 0 ! 194: $ lp -dpsu -k gauss29436.1 ! 195: gauss29436.1 removed from psu queue\*(cr ! 196: on nj/astro/coma ! 197: .P2 ! 198: If you wish to kill a job on the queue but the job has begun to print, ! 199: you then have to turn the printer off and on to kill the currently ! 200: printing job. ! 201: This may be fixed someday. ! 202: .NH ! 203: Options ! 204: .PP ! 205: There are options available to modify the way in which a job is handled. ! 206: It is the job of the ! 207: .I lp ! 208: programs to convert the option settings so they can be used by each of the ! 209: different translation and interface programs. ! 210: Not all options are applicable to all printer environments. ! 211: Table 1 lists the standard ! 212: .I lp ! 213: options, the shell variable settings and description of the options. ! 214: .1C ! 215: .KF ! 216: .SP ! 217: .TS ! 218: center; ! 219: c | c s s | c ! 220: c | c c c | c ! 221: lfCWw(.7i)| lfCWw(.6i) cfCWw(.4i) cfCWw(.6i)| lw(2.8i). ! 222: = ! 223: option shell variable action ! 224: \^ name default set \^ ! 225: _ ! 226: -D DEBUG N -D turn on debugging mode. ! 227: -H NOHEADER N 1 suppress header page. ! 228: -L LAND N 1 make long page dimension horizontal. ! 229: -M \fImach\fP LPMACHID N \fImach\fP set the source machine name. ! 230: -Q QONLY N 1 do not execute daemon; for debugging purposes. ! 231: -c \fIn\fP COPIES N \fIn\fP number of copies to be printed. ! 232: -d \fIprinter\fP LPDEST U \fIprinter\fP set job destination; override other settings. ! 233: -f \fIfont.pt\fP FONT N \fIfont\fP set font style and point size for printing. ! 234: POINT N \fIpt\fP ! 235: -i \fIn\fP IBIN N \fIn\fP T{ ! 236: select alternate paper tray. ! 237: The argument given is dependent on the printer type, ! 238: although some effort is made in the process files to make `2' ! 239: an acceptable argument. ! 240: T} ! 241: -k KILLFLAG 0 1 T{ ! 242: take non-option arguments as job numbers to be removed from queue. ! 243: T} ! 244: -l \fIn\fP LINES N \fIn\fP T{ ! 245: for printed data, the number of lines per logical page. ! 246: T} ! 247: -m \fIf\fP MAG N \fIf\fP T{ ! 248: magnify the image by a factor \fIf\fP. ! 249: The factor should be a positive real number. ! 250: T} ! 251: -n \fIn\fP NPAG N \fIn\fP T{ ! 252: put \fIn\fP logical pages on a single physical page. ! 253: A simple algorithm is used to pack the pages. ! 254: T} ! 255: -o \fIlist\fP OLIST N \fIlist\fP T{ ! 256: print only those pages specified in the list. ! 257: The list may be a sequence of numbers or ranges separated by commas. ! 258: A range is a pair of numbers separated by a hyphen. ! 259: T} ! 260: -p \fIproc\fP LPPROC L \fIproc\fP T{ ! 261: use the preprocessor \fIproc\fP instead of the preprocessor given ! 262: in the ! 263: .CW devices ! 264: file for this printer. ! 265: T} ! 266: -q LPQ N 1 T{ ! 267: print the status and queue. ! 268: T} ! 269: -r REVERSE L - T{ ! 270: this toggles the ! 271: .CW REVERSE ! 272: flag changing whether or not page reversal should occur in preprocessing. ! 273: Page reversal is needed if a printer delivers pages face up. ! 274: The keyword ! 275: .CW reverse ! 276: can be placed in the ! 277: .I lpclass ! 278: field of the ! 279: .CW devices ! 280: file. ! 281: If a document has already been processed this flag has no effect. ! 282: T} ! 283: -u \fIuser\fP LPUSERID U \fIuser\fP T{ ! 284: change the user id that appears on the cover page to \fIuser\fP. ! 285: T} ! 286: -x \fIoffset\fP XOFF N \fIoffset\fP T{ ! 287: move the image \fIoffset\fP inches to the right. ! 288: A negative \fIoffset\fP will move the image to the left. ! 289: The \fIoffset\fP may be any reasonable real number. ! 290: T} ! 291: -y \fIoffset\fP YOFF N \fIoffset\fP T{ ! 292: same as for \f(CW-x\fP except a positive offset will move the image down. ! 293: T} ! 294: _ ! 295: .T& ! 296: l l cp-2 lp-2 s ! 297: l l cfCWp-2 lp-2 s. ! 298: .vs -2p ! 299: default setting definition ! 300: N set to the null string (``'') initially in \fIlp\fP. ! 301: L set from printer entry in \f(CWdevices\fP file. ! 302: U set from the users environment. ! 303: .vs +2p ! 304: .TE ! 305: .SP ! 306: .ce ! 307: \fBTable 1. \fILp\fR Option List ! 308: .SP 4 ! 309: .KE ! 310: .2C ! 311: .NH ! 312: .CW devices ! 313: file ! 314: .PP ! 315: The ! 316: .CW devices ! 317: file is found in the spool directory. ! 318: Each line in the file is composed of 12 fields which describe the attributes ! 319: of the printer and how it should be serviced. ! 320: The following list gives the shell variable set, and a description of ! 321: each of the attributes. ! 322: .IP "\f(CWLPDEST\fP " ! 323: is the name of the device as given to ! 324: .I lp ! 325: with the ! 326: .CW -d ! 327: option ! 328: or as specified by the users shell environment variable ! 329: .CW LPDEST ! 330: or as specified by ! 331: the file ! 332: .CW $LPSPOOL/defdevice . ! 333: This name is used in creating directories and log files that are associated with ! 334: the printers operation. ! 335: .IP "\f(CWLOC\fP " ! 336: is only used to describe where the printer is located. ! 337: .IP "\f(CWDEST_HOST\fP " ! 338: is the host from which the files are printed. ! 339: Files may be spooled on other machines before being transferred to the ! 340: destination host. ! 341: .IP "\f(CWOUT_DEV\fP " ! 342: is the physical device name or network address needed by the printer daemon ! 343: to connect to the printer.* ! 344: .FS ! 345: * This field depends on the requirements of the daemon and may contain a `\(en' ! 346: if not required. ! 347: .FE ! 348: .IP "\f(CWSPEED\fP " ! 349: is the baud rate setting for the port.* ! 350: .IP "\f(CWLPCLASS\fP " ! 351: is used to distinguish minor printer differences. ! 352: For example, the keyword `reversal' is used by some of the preprocessors ! 353: to reverse the order the pages are printed to accommodate different output ! 354: trays (either face up or face down). ! 355: .IP "\f(CWLPPROC\fP " ! 356: specifies the default preprocessor to be used to convert input to a format ! 357: which will be accepted by the device. ! 358: The preprocessor is invoked by the spooler. ! 359: .IP "\f(CWSPOOLER\fP " ! 360: is the process used to invoke the preprocessor and its output in the local ! 361: spool directory. ! 362: .IP "\f(CWSTAT\fP " ! 363: prints the status of the device (whatever that means!) and the list of jobs ! 364: waiting on the queue for this device. ! 365: The status information depends on what is available from the printer ! 366: and interface software. ! 367: The queue information has been changed several times to show information ! 368: useful in tracking down problems. ! 369: The scheduler is used to show the jobs in the order ! 370: in which they will be printed. ! 371: .IP "\f(CWKILL\fP " ! 372: removes jobs from the queue. ! 373: The jobs to be removed are given as arguments to the ! 374: .I lp ! 375: command. ! 376: When possible, it should also abort the currently running job ! 377: if it has been killed. ! 378: .IP "\f(CWDAEMON\fP " ! 379: is a process that is meant to run asynchronously to remove ! 380: jobs from the queue. ! 381: Jobs may either be passed on to another host or sent to the ! 382: printing device. ! 383: .I Lp ! 384: always tries to start a daemon process when one is specified. ! 385: .IP "\f(CWSCHED\fP " ! 386: is used to present the job names to the daemon and stat programs ! 387: in some order, e.g. first-in-first-out, smallest first. ! 388: .NH ! 389: Support programs ! 390: .PP ! 391: The following sections describe the basic function of the programs ! 392: that are found in the subdirectories of ! 393: .CW LPSPOOL . ! 394: The programs in a specific directory vary the ! 395: type of output device or networks that have to be dealt with or some ! 396: special set of user requirements. ! 397: .NH 2 ! 398: .CW process ! 399: Files ! 400: .PP ! 401: The ! 402: .CW generic ! 403: preprocessor ! 404: is the default preprocessor for most printers. ! 405: It uses the ! 406: .I file (1) ! 407: command to determine the format of the input file. ! 408: The appropriate preprocessor is then selected to transform the ! 409: file to a format suitable for the printer. ! 410: .PP ! 411: Table 2 shows the names of programs that convert input formats (first column), ! 412: to output formats (top row). ! 413: .1C ! 414: .KF ! 415: .TS ! 416: center box; ! 417: c || c | c | c ! 418: c || cI | cI | cI. ! 419: P\s-2OST\s+2S\s-2CRIPT\s+2 Impress T{ ! 420: Canon ! 421: .br ! 422: (obsolete) ! 423: T} ! 424: = ! 425: text, listings ppost daisimag can ! 426: _ ! 427: troff output dpost dimp dcan ! 428: _ ! 429: Latex output (.dvi files) dvipost dviimp \(em ! 430: _ ! 431: bitmaps [see \fIbitfile\fR(9.5)] bpost bimp bcan ! 432: _ ! 433: Tektronix graphics tpost tekimag tcan ! 434: .TE ! 435: .ce ! 436: \fBTable 2.\fP ! 437: .SP 2 ! 438: .KE ! 439: .2C ! 440: .PP ! 441: There are also several interface routines here used to send ! 442: files to, e.g. the color P\s-2OST\s+2S\s-2CRIPT\s+2 printer ! 443: and the ! 444: .SM LINOTRONICS ! 445: P\s-2OST\s+2S\s-2CRIPT\s+2 phototypesetter. ! 446: .NH 2 ! 447: .CW spool ! 448: Files ! 449: .PP ! 450: The generic spooler is responsible for executing the preprocessor ! 451: and directing its output to a file in the printers queue. ! 452: An additional file is created containing information such as the system name, ! 453: user id, job number, and number of times this job was attempted. ! 454: The format of the id file has been changed from time to time ! 455: to assist with debugging. ! 456: .PP ! 457: Certain printer handling programs do not require separate preprocessing ! 458: and spooling. ! 459: For such circumstances a ! 460: .CW nospool ! 461: spooler is available which simply executes the preprocessing program. ! 462: The processing and spooling functions are assumed by this program. ! 463: .NH 2 ! 464: .CW stat ! 465: Files ! 466: .PP ! 467: The function of these files is to present status information about the ! 468: printer and its queue. ! 469: Because ! 470: .I lp ! 471: often works over a network connection, the stat function is designed ! 472: to return information about the local queue as well as the remote queue. ! 473: The scheduler is used to print the queue in the order in which the jobs ! 474: will be executed. ! 475: The various commands in the ! 476: .CW stat ! 477: directory differ only in the means in which they access different networks. ! 478: .NH 2 ! 479: .CW kill ! 480: Files ! 481: .PP ! 482: These programs receive command line arguments passed to them by ! 483: .I lp ! 484: and remove the job and id files which match the arguments ! 485: from the particular queue. ! 486: .NH 2 ! 487: .CW daemon ! 488: Files ! 489: .PP ! 490: The ! 491: daemon is the last program invoked by ! 492: .I lp ! 493: if the \f(CW-Q\fP option has not been given. ! 494: The daemon process is executed asynchronously ! 495: with its standard output and standard error appended to ! 496: the printer log file. ! 497: The log file is described in a subsequent section. ! 498: Because the daemon runs asynchronously, it must ! 499: catch signals that could cause it to terminate abnormally. ! 500: The daemon first checks to see that it is the only one running ! 501: by using the ! 502: .CW LOCK ! 503: program found in the daemon directory. ! 504: The daemon then executes the scheduler to obtain the name of the ! 505: next job on the queue. ! 506: .PP ! 507: The processing of jobs may entail transfer to another host ! 508: or transmission to a printer. ! 509: The details of this are specific to the individual daemons. ! 510: If a job is processed without error, it is removed from the queue. ! 511: If a job does not succeed, the associated files may be ! 512: moved to a printer specific directory in ! 513: \f(CW$LPSPOOL/prob\fP. ! 514: In either case, the daemon can make an entry in the printer's ! 515: log file. ! 516: Before exiting, the daemon should clean up lock files by calling ! 517: .SM \fIUNLOCK\fP . ! 518: .PP ! 519: The ! 520: .SM \fILOCK\fP ! 521: command creates a ! 522: .CW LOCK ! 523: file in the printer's queue and makes a link to a file called ! 524: .CW LINK . ! 525: The locking mechanism could be improved but there have been very ! 526: few failures. ! 527: .PP ! 528: Several non-standard daemon programs have been designed ! 529: to suite various requirements and whims. ! 530: One such program announces job completion and empty paper trays ! 531: by causing icons to appear in peoples' ! 532: .I vismon (9.1) ! 533: window. ! 534: Another, using a voice synthesizer, makes verbal announcements. ! 535: Other daemons may be designed to taste. ! 536: .NH 2 ! 537: .CW sched ! 538: Files ! 539: .PP ! 540: The scheduler must decide which job files should be executed and ! 541: in what order. ! 542: The most commonly used scheduler algorithm is FIFO, which looks like this: ! 543: .P1 0 ! 544: ls -tr $* | sed -n -e 's/.* *//' \e ! 545: -e '/^[0-9][0-9]*\.[1-9][0-9]*$/p' ! 546: .P2 ! 547: This lists all the job files in this printer's queue in modification ! 548: time order. ! 549: Jobs entering the queue have a dot (.) prepended to their name ! 550: to keep the scheduler from selecting them before they are complete. ! 551: .NH ! 552: When Thing Go Wrong ! 553: .NH 2 ! 554: .CW log ! 555: Files ! 556: .PP ! 557: The log files for a particular ! 558: .I printer ! 559: appear in a subdirectory of the spool directory ! 560: .CW log/printer . ! 561: There are currently two types of log files that appear ! 562: here. ! 563: One is for the daemon to log errors and successful completions ! 564: of jobs. ! 565: These are named ! 566: .I printer.day ! 567: where day is the three letter abbreviation for the day of the week. ! 568: These are overwritten once a week to avoid the need for regular ! 569: cleanup. ! 570: The other type of log file contains the status of the printer and ! 571: is written by the program that communicates with the printer itself. ! 572: These are named ! 573: .I printer.st . ! 574: These are overwritten with each new job and are saved in the ! 575: .I prob ! 576: directory along with the job under circumstances described below. ! 577: When a printer does not appear to be functioning these files are the ! 578: place to look first. ! 579: .NH 2 ! 580: .I prob ! 581: Files ! 582: .PP ! 583: When a job fails to produce output, ! 584: the log files should be checked for any obvious problems. ! 585: If none can be found, a directory with full read and write permissions ! 586: should be created with the name of the printer in the ! 587: .CW $LPSPOOL/prob ! 588: directory. ! 589: Subsequent failure of that job will cause the daemon to leave a ! 590: copy of the job and the printer communication log in the ! 591: printers ! 592: .I prob ! 593: directory. ! 594: It is not uncommon for a printer to enter states from which ! 595: it cannot be rescued except by manually resetting it. ! 596: .NH 2 ! 597: Repairing Stuck Daemons ! 598: .PP ! 599: There are two failure conditions that occur which are not handled ! 600: by the daemons. ! 601: .PP ! 602: One problem can only be described as the printer entering a ! 603: comatose state. ! 604: The printer does not respond to any messages sent to it. ! 605: The daemon should recover from the reset and an error message ! 606: will appear in the log files. ! 607: .PP ! 608: The second problem is more insidious. ! 609: When communicating with a printer directly connected to Datakit, ! 610: or when transferring files between a remote and local host over ! 611: Datakit, ! 612: the Datakit channel can become ! 613: frozen and the I/O process hangs. ! 614: The I/O process must be killed and another must be allowed to start ! 615: up. ! 616: The ultimate cure for this problem lies in another domain. ! 617: ....... ! 618: .NH ! 619: Interprocessor Communication ! 620: .PP ! 621: When a Tenth Edition ! 622: .UX ! 623: System is first being set up as a printer host, ! 624: two files need to be edited. ! 625: (Sample lines are shown in Figure 2.) ! 626: .CW /usr/ipc/lib/serv.local ! 627: needs to define the ! 628: .I lp ! 629: service. ! 630: Authorization lines need to be added to ! 631: .CW /usr/ipc/lib/auth.local , ! 632: permitting certain machines ! 633: (in this case any machine on the ! 634: .CW alpha ! 635: or ! 636: .CW beta ! 637: Datakit nodes) to use the ! 638: .I lp ! 639: service as the user ! 640: .CW daemon ! 641: on this machine. ! 642: The function of all these lines is explained in more detail in ! 643: |reference(latest ipc presotto). ! 644: .1C ! 645: .KF ! 646: .P1 10n ! 647: /usr/ipc/lib/serv.local: ! 648: .sp .3 ! 649: #service actions ! 650: lp v9auth+args+cmd(/usr/bin/lp) ! 651: ! 652: /usr/ipc/lib/auth.local: ! 653: .sp .3 ! 654: #service remote-hosts rem-uid local-uid ! 655: lp dk!nj/(alpha|beta)/.* .* daemon ! 656: .P2 ! 657: .SP ! 658: .ce ! 659: \fBFigure 2.\fR IPC configuration lines ! 660: .KE ! 661: .2C ! 662: .PP ! 663: The use of ! 664: .I lp ! 665: over Ethernet ! 666: is either more complicated or more restricted in the way ! 667: .I lp ! 668: can be used. ! 669: Because ! 670: .I lp ! 671: does not run with special setuid permissions, users must have ! 672: permission to execute the command remotely. ! 673: Otherwise, a special program ! 674: would have to be written to handle the I/O setup for the ! 675: .I lp ! 676: program. ! 677: .NH ! 678: Acknowledgements ! 679: .PP ! 680: Special thanks to Rich Drechsler for supplying and maintaining all ! 681: the P\s-2OST\s+2S\s-2CRIPT\s+2 translation and interface programs, ! 682: without which ! 683: .I lp ! 684: would be an empty shell. ! 685: Howard Trickey provided the ! 686: T\s-2E\s+2X ! 687: to P\s-2OST\s+2S\s-2CRIPT\s+2 ! 688: translation program. ! 689: .NH ! 690: References ! 691: .LP ! 692: |reference_placement
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.