From 862fdf11a2ede45dec0da01ed575525d79468981 Mon Sep 17 00:00:00 2001 From: rgrimes Date: Thu, 26 May 1994 05:23:31 +0000 Subject: BSD 4.4 Lite usr.sbin Sources --- usr.sbin/lpr/Makefile | 6 + usr.sbin/lpr/SMM.doc/0.t | 68 ++ usr.sbin/lpr/SMM.doc/1.t | 77 ++ usr.sbin/lpr/SMM.doc/2.t | 141 +++ usr.sbin/lpr/SMM.doc/3.t | 73 ++ usr.sbin/lpr/SMM.doc/4.t | 206 +++++ usr.sbin/lpr/SMM.doc/5.t | 116 +++ usr.sbin/lpr/SMM.doc/6.t | 94 ++ usr.sbin/lpr/SMM.doc/7.t | 226 +++++ usr.sbin/lpr/SMM.doc/Makefile | 10 + usr.sbin/lpr/SMM.doc/spell.ok | 70 ++ usr.sbin/lpr/common_source/common.c | 352 ++++++++ usr.sbin/lpr/common_source/displayq.c | 449 ++++++++++ usr.sbin/lpr/common_source/lp.h | 126 +++ usr.sbin/lpr/common_source/lp.local.h | 80 ++ usr.sbin/lpr/common_source/pathnames.h | 50 ++ usr.sbin/lpr/common_source/printcap.c | 458 ++++++++++ usr.sbin/lpr/common_source/rmjob.c | 339 ++++++++ usr.sbin/lpr/common_source/startdaemon.c | 108 +++ usr.sbin/lpr/filters/Makefile | 7 + usr.sbin/lpr/filters/lpf.c | 217 +++++ usr.sbin/lpr/lpc/Makefile | 12 + usr.sbin/lpr/lpc/cmds.c | 1107 ++++++++++++++++++++++++ usr.sbin/lpr/lpc/cmdtab.c | 79 ++ usr.sbin/lpr/lpc/extern.h | 58 ++ usr.sbin/lpr/lpc/lpc.8 | 174 ++++ usr.sbin/lpr/lpc/lpc.c | 277 ++++++ usr.sbin/lpr/lpc/lpc.h | 45 + usr.sbin/lpr/lpd/Makefile | 11 + usr.sbin/lpr/lpd/extern.h | 39 + usr.sbin/lpr/lpd/lpd.8 | 249 ++++++ usr.sbin/lpr/lpd/lpd.c | 507 +++++++++++ usr.sbin/lpr/lpd/lpdchar.c | 1066 +++++++++++++++++++++++ usr.sbin/lpr/lpd/printjob.c | 1377 ++++++++++++++++++++++++++++++ usr.sbin/lpr/lpd/recvjob.c | 358 ++++++++ usr.sbin/lpr/lpq/Makefile | 12 + usr.sbin/lpr/lpq/lpq.1 | 134 +++ usr.sbin/lpr/lpq/lpq.c | 126 +++ usr.sbin/lpr/lpr/Makefile | 12 + usr.sbin/lpr/lpr/lpr.1 | 256 ++++++ usr.sbin/lpr/lpr/lpr.c | 744 ++++++++++++++++ usr.sbin/lpr/lprm/Makefile | 12 + usr.sbin/lpr/lprm/lprm.1 | 145 ++++ usr.sbin/lpr/lprm/lprm.c | 144 ++++ usr.sbin/lpr/lptest/Makefile | 6 + usr.sbin/lpr/lptest/lptest.1 | 74 ++ usr.sbin/lpr/lptest/lptest.c | 83 ++ usr.sbin/lpr/pac/Makefile | 10 + usr.sbin/lpr/pac/pac.8 | 106 +++ usr.sbin/lpr/pac/pac.c | 444 ++++++++++ 50 files changed, 10940 insertions(+) create mode 100644 usr.sbin/lpr/Makefile create mode 100644 usr.sbin/lpr/SMM.doc/0.t create mode 100644 usr.sbin/lpr/SMM.doc/1.t create mode 100644 usr.sbin/lpr/SMM.doc/2.t create mode 100644 usr.sbin/lpr/SMM.doc/3.t create mode 100644 usr.sbin/lpr/SMM.doc/4.t create mode 100644 usr.sbin/lpr/SMM.doc/5.t create mode 100644 usr.sbin/lpr/SMM.doc/6.t create mode 100644 usr.sbin/lpr/SMM.doc/7.t create mode 100644 usr.sbin/lpr/SMM.doc/Makefile create mode 100644 usr.sbin/lpr/SMM.doc/spell.ok create mode 100644 usr.sbin/lpr/common_source/common.c create mode 100644 usr.sbin/lpr/common_source/displayq.c create mode 100644 usr.sbin/lpr/common_source/lp.h create mode 100644 usr.sbin/lpr/common_source/lp.local.h create mode 100644 usr.sbin/lpr/common_source/pathnames.h create mode 100644 usr.sbin/lpr/common_source/printcap.c create mode 100644 usr.sbin/lpr/common_source/rmjob.c create mode 100644 usr.sbin/lpr/common_source/startdaemon.c create mode 100644 usr.sbin/lpr/filters/Makefile create mode 100644 usr.sbin/lpr/filters/lpf.c create mode 100644 usr.sbin/lpr/lpc/Makefile create mode 100644 usr.sbin/lpr/lpc/cmds.c create mode 100644 usr.sbin/lpr/lpc/cmdtab.c create mode 100644 usr.sbin/lpr/lpc/extern.h create mode 100644 usr.sbin/lpr/lpc/lpc.8 create mode 100644 usr.sbin/lpr/lpc/lpc.c create mode 100644 usr.sbin/lpr/lpc/lpc.h create mode 100644 usr.sbin/lpr/lpd/Makefile create mode 100644 usr.sbin/lpr/lpd/extern.h create mode 100644 usr.sbin/lpr/lpd/lpd.8 create mode 100644 usr.sbin/lpr/lpd/lpd.c create mode 100644 usr.sbin/lpr/lpd/lpdchar.c create mode 100644 usr.sbin/lpr/lpd/printjob.c create mode 100644 usr.sbin/lpr/lpd/recvjob.c create mode 100644 usr.sbin/lpr/lpq/Makefile create mode 100644 usr.sbin/lpr/lpq/lpq.1 create mode 100644 usr.sbin/lpr/lpq/lpq.c create mode 100644 usr.sbin/lpr/lpr/Makefile create mode 100644 usr.sbin/lpr/lpr/lpr.1 create mode 100644 usr.sbin/lpr/lpr/lpr.c create mode 100644 usr.sbin/lpr/lprm/Makefile create mode 100644 usr.sbin/lpr/lprm/lprm.1 create mode 100644 usr.sbin/lpr/lprm/lprm.c create mode 100644 usr.sbin/lpr/lptest/Makefile create mode 100644 usr.sbin/lpr/lptest/lptest.1 create mode 100644 usr.sbin/lpr/lptest/lptest.c create mode 100644 usr.sbin/lpr/pac/Makefile create mode 100644 usr.sbin/lpr/pac/pac.8 create mode 100644 usr.sbin/lpr/pac/pac.c (limited to 'usr.sbin/lpr') diff --git a/usr.sbin/lpr/Makefile b/usr.sbin/lpr/Makefile new file mode 100644 index 0000000..9b4d7d2 --- /dev/null +++ b/usr.sbin/lpr/Makefile @@ -0,0 +1,6 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +SUBDIR= lpc lpd lpq lpr lprm lptest pac filters + +.include + diff --git a/usr.sbin/lpr/SMM.doc/0.t b/usr.sbin/lpr/SMM.doc/0.t new file mode 100644 index 0000000..65ecd4e --- /dev/null +++ b/usr.sbin/lpr/SMM.doc/0.t @@ -0,0 +1,68 @@ +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)0.t 8.1 (Berkeley) 6/8/93 +.\" +.if n .ND +.TL +4.3BSD Line Printer Spooler Manual +.EH 'SMM:7-%''4.3BSD Line Printer Spooler Manual' +.OH '4.3BSD Line Printer Spooler Manual''SMM:7-%' +.AU +Ralph Campbell +.AI +Computer Systems Research Group +Computer Science Division +Department of Electrical Engineering and Computer Science +University of California, Berkeley +Berkeley, CA 94720 +.AB +.FS +* UNIX is a trademark of Bell Laboratories. +.FE +This document describes the structure and installation procedure +for the line printer spooling system +developed for the 4.3BSD version +of the UNIX* operating system. +.de D? +.ie \\n(.$>1 Revised \\$1 \\$2 \\$3 +.el DRAFT of \n(mo/\n(dy/\n(yr +.. +.sp 2 +.LP +.D? June 8, 1993 +.AE +.de IR +\fI\\$1\fP\\$2 +.. +.de DT +.TA 8 16 24 32 40 48 56 64 72 80 +.. diff --git a/usr.sbin/lpr/SMM.doc/1.t b/usr.sbin/lpr/SMM.doc/1.t new file mode 100644 index 0000000..1d34e9e --- /dev/null +++ b/usr.sbin/lpr/SMM.doc/1.t @@ -0,0 +1,77 @@ +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)1.t 8.1 (Berkeley) 6/8/93 +.\" +.NH 1 +Overview +.PP +The line printer system supports: +.IP \(bu 3 +multiple printers, +.IP \(bu 3 +multiple spooling queues, +.IP \(bu 3 +both local and remote +printers, and +.IP \(bu 3 +printers attached via serial lines that require +line initialization such as the baud rate. +.LP +Raster output devices +such as a Varian or Versatec, and laser printers such as an Imagen, +are also supported by the line printer system. +.PP +The line printer system consists mainly of the +following files and commands: +.DS +.TS +l l. +/etc/printcap printer configuration and capability data base +/usr/lib/lpd line printer daemon, does all the real work +/usr/ucb/lpr program to enter a job in a printer queue +/usr/ucb/lpq spooling queue examination program +/usr/ucb/lprm program to delete jobs from a queue +/etc/lpc program to administer printers and spooling queues +/dev/printer socket on which lpd listens +.TE +.DE +The file /etc/printcap is a master data base describing line +printers directly attached to a machine and, also, printers +accessible across a network. The manual page entry +.IR printcap (5) +provides the authoritative definition of +the format of this data base, as well as +specifying default values for important items +such as the directory in which spooling is performed. +This document introduces some of the +information that may be placed +.IR printcap . diff --git a/usr.sbin/lpr/SMM.doc/2.t b/usr.sbin/lpr/SMM.doc/2.t new file mode 100644 index 0000000..9da2ae2 --- /dev/null +++ b/usr.sbin/lpr/SMM.doc/2.t @@ -0,0 +1,141 @@ +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)2.t 8.1 (Berkeley) 6/8/93 +.\" +.NH 1 +Commands +.NH 2 +lpd \- line printer daemon +.PP +The program +.IR lpd (8), +usually invoked at boot time from the /etc/rc file, acts as +a master server for coordinating and controlling +the spooling queues configured in the printcap file. +When +.I lpd +is started it makes a single pass through the +.I printcap +database restarting any printers that have jobs. +In normal operation +.I lpd +listens for service requests on multiple sockets, +one in the UNIX domain (named ``/dev/printer'') for +local requests, and one in the Internet domain +(under the ``printer'' service specification) +for requests for printer access from off machine; +see \fIsocket\fP\|(2) and \fIservices\fP\|(5) +for more information on sockets and service +specifications, respectively. +.I Lpd +spawns a copy of itself to process the request; the master daemon +continues to listen for new requests. +.PP +Clients communicate with +.I lpd +using a simple transaction oriented protocol. +Authentication of remote clients is done based +on the ``privilege port'' scheme employed by +\fIrshd\fP\|(8C) and \fIrcmd\fP\|(3X). +The following table shows the requests +understood by +.IR lpd . +In each request the first byte indicates the +``meaning'' of the request, followed by the name +of the printer to which it should be applied. Additional +qualifiers may follow, depending on the request. +.DS +.TS +l l. +Request Interpretation +_ +^Aprinter\en check the queue for jobs and print any found +^Bprinter\en receive and queue a job from another machine +^Cprinter [users ...] [jobs ...]\en return short list of current queue state +^Dprinter [users ...] [jobs ...]\en return long list of current queue state +^Eprinter person [users ...] [jobs ...]\en remove jobs from a queue +.TE +.DE +.PP +The \fIlpr\fP\|(1) command +is used by users to enter a print job in a local queue and to notify +the local +.I lpd +that there are new jobs in the spooling area. +.I Lpd +either schedules the job to be printed locally, or if +printing remotely, attempts to forward +the job to the appropriate machine. +If the printer cannot be opened or the destination +machine is unreachable, the job will remain queued until it is +possible to complete the work. +.NH 2 +lpq \- show line printer queue +.PP +The \fIlpq\fP\|(1) +program works recursively backwards displaying the queue of the machine with +the printer and then the queue(s) of the machine(s) that lead to it. +.I Lpq +has two forms of output: in the default, short, format it +gives a single line of output per queued job; in the long +format it shows the list of files, and their sizes, that +comprise a job. +.NH 2 +lprm \- remove jobs from a queue +.PP +The \fIlprm\fP\|(1) command deletes jobs from a spooling +queue. If necessary, \fIlprm\fP will first kill off a +running daemon that is servicing the queue and restart +it after the required files are removed. When removing +jobs destined for a remote printer, \fIlprm\fP acts +similarly to \fIlpq\fP except it first checks locally +for jobs to remove and then +tries to remove files in queues off-machine. +.NH 2 +lpc \- line printer control program +.PP +The +.IR lpc (8) +program is used by the system administrator to control the +operation of the line printer system. +For each line printer configured in /etc/printcap, +.I lpc +may be used to: +.IP \(bu +disable or enable a printer, +.IP \(bu +disable or enable a printer's spooling queue, +.IP \(bu +rearrange the order of jobs in a spooling queue, +.IP \(bu +find the status of printers, and their associated +spooling queues and printer daemons. diff --git a/usr.sbin/lpr/SMM.doc/3.t b/usr.sbin/lpr/SMM.doc/3.t new file mode 100644 index 0000000..8c950a9 --- /dev/null +++ b/usr.sbin/lpr/SMM.doc/3.t @@ -0,0 +1,73 @@ +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)3.t 8.1 (Berkeley) 6/8/93 +.\" +.NH 1 +Access control +.PP +The printer system maintains protected spooling areas so that +users cannot circumvent printer accounting or +remove files other than their own. +The strategy used to maintain protected +spooling areas is as follows: +.IP \(bu 3 +The spooling area is writable only by a \fIdaemon\fP user +and \fIdaemon\fP group. +.IP \(bu 3 +The \fIlpr\fP program runs set-user-id to \fIroot\fP and +set-group-id to group \fIdaemon\fP. The \fIroot\fP access permits +reading any file required. Accessibility is verified +with an \fIaccess\fP\|(2) call. The group ID +is used in setting up proper ownership of files +in the spooling area for \fIlprm\fP. +.IP \(bu 3 +Control files in a spooling area are made with \fIdaemon\fP +ownership and group ownership \fIdaemon\fP. Their mode is 0660. +This insures control files are not modified by a user +and that no user can remove files except through \fIlprm\fP. +.IP \(bu 3 +The spooling programs, +\fIlpd\fP, \fIlpq\fP, and \fIlprm\fP run set-user-id to \fIroot\fP +and set-group-id to group \fIdaemon\fP to access spool files and printers. +.IP \(bu 3 +The printer server, \fIlpd\fP, +uses the same verification procedures as \fIrshd\fP\|(8C) +in authenticating remote clients. The host on which a client +resides must be present in the file /etc/hosts.equiv or /etc/hosts.lpd and +the request message must come from a reserved port number. +.PP +In practice, none of \fIlpd\fP, \fIlpq\fP, or +\fIlprm\fP would have to run as user \fIroot\fP if remote +spooling were not supported. In previous incarnations of +the printer system \fIlpd\fP ran set-user-id to \fIdaemon\fP, +set-group-id to group \fIspooling\fP, and \fIlpq\fP and \fIlprm\fP ran +set-group-id to group \fIspooling\fP. diff --git a/usr.sbin/lpr/SMM.doc/4.t b/usr.sbin/lpr/SMM.doc/4.t new file mode 100644 index 0000000..8800bc0 --- /dev/null +++ b/usr.sbin/lpr/SMM.doc/4.t @@ -0,0 +1,206 @@ +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)4.t 8.1 (Berkeley) 6/8/93 +.\" +.NH 1 +Setting up +.PP +The 4.3BSD release comes with the necessary programs +installed and with the default line printer queue +created. If the system must be modified, the +makefile in the directory /usr/src/usr.lib/lpr +should be used in recompiling and reinstalling +the necessary programs. +.PP +The real work in setting up is to create the +.I printcap +file and any printer filters for printers not supported +in the distribution system. +.NH 2 +Creating a printcap file +.PP +The +.I printcap +database contains one or more entries per printer. +A printer should have a separate spooling directory; +otherwise, jobs will be printed on +different printers depending on which printer daemon starts first. +This section describes how to create entries for printers that do not +conform to the default printer description (an LP-11 style interface to a +standard, band printer). +.NH 3 +Printers on serial lines +.PP +When a printer is connected via a serial communication line +it must have the proper baud rate and terminal modes set. +The following example is for a DecWriter III printer connected +locally via a 1200 baud serial line. +.DS +.DT +lp|LA-180 DecWriter III:\e + :lp=/dev/lp:br#1200:fs#06320:\e + :tr=\ef:of=/usr/lib/lpf:lf=/usr/adm/lpd-errs: +.DE +The +.B lp +entry specifies the file name to open for output. Here it could +be left out since ``/dev/lp'' is the default. +The +.B br +entry sets the baud rate for the tty line and the +.B fs +entry sets CRMOD, no parity, and XTABS (see \fItty\fP\|(4)). +The +.B tr +entry indicates that a form-feed should be printed when the queue +empties so the paper can be torn off without turning the printer off-line and +pressing form feed. +The +.B of +entry specifies the filter program +.I lpf +should be used for printing the files; +more will be said about filters later. +The last entry causes errors +to be written to the file ``/usr/adm/lpd-errs'' +instead of the console. Most errors from \fIlpd\fP are logged using +\fIsyslogd\fP\|(8) and will not be logged in the specified file. The +filters should use \fIsyslogd\fP to report errors; only those that +write to standard error output will end up with errors in the \fBlf\fP file. +(Occasionally errors sent to standard error output have not appeared +in the log file; the use of \fIsyslogd\fP is highly recommended.) +.NH 3 +Remote printers +.PP +Printers that reside on remote hosts should have an empty +.B lp +entry. +For example, the following printcap entry would send output to the printer +named ``lp'' on the machine ``ucbvax''. +.DS +.DT +lp|default line printer:\e + :lp=:rm=ucbvax:rp=lp:sd=/usr/spool/vaxlpd: +.DE +The +.B rm +entry is the name of the remote machine to connect to; this name must +be a known host name for a machine on the network. +The +.B rp +capability indicates +the name of the printer on the remote machine is ``lp''; +here it could be left out since this is the default value. +The +.B sd +entry specifies ``/usr/spool/vaxlpd'' +as the spooling directory instead of the +default value of ``/usr/spool/lpd''. +.NH 2 +Output filters +.PP +Filters are used to handle device dependencies and to +do accounting functions. The output filtering of +.B of +is used when accounting is +not being done or when all text data must be passed through a filter. +It is not intended to do accounting since it is started only once, +all text files are filtered through it, and no provision is made for passing +owners' login name, identifying the beginning and ending of jobs, etc. +The other filters (if specified) are started for each file +printed and do accounting if there is an +.B af +entry. +If entries for both +.B of +and other filters are specified, +the output filter is used only to print the banner page; +it is then stopped to allow other filters access to the printer. +An example of a printer that requires output filters +is the Benson-Varian. +.DS +.DT +va|varian|Benson-Varian:\e + :lp=/dev/va0:sd=/usr/spool/vad:of=/usr/lib/vpf:\e + :tf=/usr/lib/rvcat:mx#2000:pl#58:px=2112:py=1700:tr=\ef: +.DE +The +.B tf +entry specifies ``/usr/lib/rvcat'' as the filter to be +used in printing \fItroff\fP\|(1) output. +This filter is needed to set the device into print mode +for text, and plot mode for printing +.I troff +files and raster images (see \fIva\fP\|(4V)). +Note that the page length is set to 58 lines by the +.B pl +entry for 8.5" by 11" fan-fold paper. +To enable accounting, the varian entry would be +augmented with an +.B af +filter as shown below. +.DS +.DT +va|varian|Benson-Varian:\e + :lp=/dev/va0:sd=/usr/spool/vad:of=/usr/lib/vpf:\e + :if=/usr/lib/vpf:tf=/usr/lib/rvcat:af=/usr/adm/vaacct:\e + :mx#2000:pl#58:px=2112:py=1700:tr=\ef: +.DE +.NH 2 +Access Control +.PP +Local access to printer queues is controlled with the +.B rg +printcap entry. +.DS + :rg=lprgroup: +.DE +Users must be in the group +.I lprgroup +to submit jobs to the specified printer. +The default is to allow all users access. +Note that once the files are in the local queue, they can be printed +locally or forwarded to another host depending on the configuration. +.PP +Remote access is controlled by listing the hosts in either the file +/etc/hosts.equiv or /etc/hosts.lpd, one host per line. Note that +.IR rsh (1) +and +.IR rlogin (1) +use /etc/hosts.equiv to determine which hosts are equivalent for allowing logins +without passwords. The file /etc/hosts.lpd is only used to control +which hosts have line printer access. +Remote access can be further restricted to only allow remote users with accounts +on the local host to print jobs by using the \fBrs\fP printcap entry. +.DS + :rs: +.DE diff --git a/usr.sbin/lpr/SMM.doc/5.t b/usr.sbin/lpr/SMM.doc/5.t new file mode 100644 index 0000000..137a342 --- /dev/null +++ b/usr.sbin/lpr/SMM.doc/5.t @@ -0,0 +1,116 @@ +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)5.t 8.1 (Berkeley) 6/8/93 +.\" +.NH 1 +Output filter specifications +.PP +The filters supplied with 4.3BSD +handle printing and accounting for most common +line printers, the Benson-Varian, the wide (36") and +narrow (11") Versatec printer/plotters. For other devices or accounting +methods, it may be necessary to create a new filter. +.PP +Filters are spawned by \fIlpd\fP +with their standard input the data to be printed, and standard output +the printer. The standard error is attached to the +.B lf +file for logging errors or \fIsyslogd\fP may be used for logging errors. +A filter must return a 0 exit +code if there were no errors, 1 if the job should be reprinted, +and 2 if the job should be thrown away. +When \fIlprm\fP +sends a kill signal to the \fIlpd\fP process controlling +printing, it sends a SIGINT signal +to all filters and descendents of filters. +This signal can be trapped by filters that need +to do cleanup operations such as +deleting temporary files. +.PP +Arguments passed to a filter depend on its type. +The +.B of +filter is called with the following arguments. +.DS +\fIfilter\fP \fB\-w\fPwidth \fB\-l\fPlength +.DE +The \fIwidth\fP and \fIlength\fP values come from the +.B pw +and +.B pl +entries in the printcap database. +The +.B if +filter is passed the following parameters. +.DS +\fIfilter\fP [\|\fB\-c\fP\|] \fB\-w\fPwidth \fB\-l\fPlength \fB\-i\fPindent \fB\-n\fP login \fB\-h\fP host accounting_file +.DE +The +.B \-c +flag is optional, and only supplied when control characters +are to be passed uninterpreted to the printer (when using the +.B \-l +option of +.I lpr +to print the file). +The +.B \-w +and +.B \-l +parameters are the same as for the +.B of +filter. +The +.B \-n +and +.B \-h +parameters specify the login name and host name of the job owner. +The last argument is the name of the accounting file from +.IR printcap . +.PP +All other filters are called with the following arguments: +.DS +\fIfilter\fP \fB\-x\fPwidth \fB\-y\fPlength \fB\-n\fP login \fB\-h\fP host accounting_file +.DE +The +.B \-x +and +.B \-y +options specify the horizontal and vertical page +size in pixels (from the +.B px +and +.B py +entries in the printcap file). +The rest of the arguments are the same as for the +.B if +filter. diff --git a/usr.sbin/lpr/SMM.doc/6.t b/usr.sbin/lpr/SMM.doc/6.t new file mode 100644 index 0000000..7087790 --- /dev/null +++ b/usr.sbin/lpr/SMM.doc/6.t @@ -0,0 +1,94 @@ +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)6.t 8.1 (Berkeley) 6/8/93 +.\" +.NH 1 +Line printer Administration +.PP +The +.I lpc +program provides local control over line printer activity. +The major commands and their intended use will be described. +The command format and remaining commands are described in +.IR lpc (8). +.LP +\fBabort\fP and \fBstart\fP +.IP +.I Abort +terminates an active spooling daemon on the local host immediately and +then disables printing (preventing new daemons from being started by +.IR lpr ). +This is normally used to forcibly restart a hung line printer daemon +(i.e., \fIlpq\fP reports that there is a daemon present but nothing is +happening). It does not remove any jobs from the queue +(use the \fIlprm\fP command instead). +.I Start +enables printing and requests \fIlpd\fP to start printing jobs. +.LP +\fBenable\fP and \fBdisable\fP +.IP +\fIEnable\fP and \fIdisable\fP allow spooling in the local queue to be +turned on/off. +This will allow/prevent +.I lpr +from putting new jobs in the spool queue. It is frequently convenient +to turn spooling off while testing new line printer filters since the +.I root +user can still use +.I lpr +to put jobs in the queue but no one else can. +The other main use is to prevent users from putting jobs in the queue +when the printer is expected to be unavailable for a long time. +.LP +\fBrestart\fP +.IP +.I Restart +allows ordinary users to restart printer daemons when +.I lpq +reports that there is no daemon present. +.LP +\fBstop\fP +.IP +.I Stop +halts a spooling daemon after the current job completes; +this also disables printing. This is a clean way to shutdown a +printer to do maintenance, etc. Note that users can still enter jobs in a +spool queue while a printer is +.IR stopped . +.LP +\fBtopq\fP +.IP +.I Topq +places jobs at the top of a printer queue. This can be used +to reorder high priority jobs since +.I lpr +only provides first-come-first-serve ordering of jobs. diff --git a/usr.sbin/lpr/SMM.doc/7.t b/usr.sbin/lpr/SMM.doc/7.t new file mode 100644 index 0000000..a6f6bea --- /dev/null +++ b/usr.sbin/lpr/SMM.doc/7.t @@ -0,0 +1,226 @@ +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)7.t 8.1 (Berkeley) 6/8/93 +.\" +.NH 1 +Troubleshooting +.PP +There are several messages that may be generated by the +the line printer system. This section +categorizes the most common and explains the cause +for their generation. Where the message implies a failure, +directions are given to remedy the problem. +.PP +In the examples below, the name +.I printer +is the name of the printer from the +.I printcap +database. +.NH 2 +LPR +.SH +lpr: \fIprinter\fP\|: unknown printer +.IP +The +.I printer +was not found in the +.I printcap +database. Usually this is a typing mistake; however, it may indicate +a missing or incorrect entry in the /etc/printcap file. +.SH +lpr: \fIprinter\fP\|: jobs queued, but cannot start daemon. +.IP +The connection to +.I lpd +on the local machine failed. +This usually means the printer server started at +boot time has died or is hung. Check the local socket +/dev/printer to be sure it still exists (if it does not exist, +there is no +.I lpd +process running). +Usually it is enough to get a super-user to type the following to +restart +.IR lpd . +.DS +% /usr/lib/lpd +.DE +You can also check the state of the master printer daemon with the following. +.DS +% ps l`cat /usr/spool/lpd.lock` +.DE +.IP +Another possibility is that the +.I lpr +program is not set-user-id to \fIroot\fP, set-group-id to group \fIdaemon\fP. +This can be checked with +.DS +% ls \-lg /usr/ucb/lpr +.DE +.SH +lpr: \fIprinter\fP\|: printer queue is disabled +.IP +This means the queue was turned off with +.DS +% lpc disable \fIprinter\fP +.DE +to prevent +.I lpr +from putting files in the queue. This is normally +done by the system manager when a printer is +going to be down for a long time. The +printer can be turned back on by a super-user with +.IR lpc . +.NH 2 +LPQ +.SH +waiting for \fIprinter\fP to become ready (offline ?) +.IP +The printer device could not be opened by the daemon. +This can happen for several reasons, +the most common is that the printer is turned off-line. +This message can also be generated if the printer is out +of paper, the paper is jammed, etc. +The actual reason is dependent on the meaning +of error codes returned by system device driver. +Not all printers supply enough information +to distinguish when a printer is off-line or having +trouble (e.g. a printer connected through a serial line). +Another possible cause of this message is +some other process, such as an output filter, +has an exclusive open on the device. Your only recourse +here is to kill off the offending program(s) and +restart the printer with +.IR lpc . +.SH +\fIprinter\fP is ready and printing +.IP +The +.I lpq +program checks to see if a daemon process exists for +.I printer +and prints the file \fIstatus\fP located in the spooling directory. +If the daemon is hung, a super user can use +.I lpc +to abort the current daemon and start a new one. +.SH +waiting for \fIhost\fP to come up +.IP +This implies there is a daemon trying to connect to the remote +machine named +.I host +to send the files in the local queue. +If the remote machine is up, +.I lpd +on the remote machine is probably dead or +hung and should be restarted as mentioned for +.IR lpr . +.SH +sending to \fIhost\fP +.IP +The files should be in the process of being transferred to the remote +.IR host . +If not, the local daemon should be aborted and started with +.IR lpc . +.SH +Warning: \fIprinter\fP is down +.IP +The printer has been marked as being unavailable with +.IR lpc . +.SH +Warning: no daemon present +.IP +The \fIlpd\fP process overseeing +the spooling queue, as specified in the ``lock'' file +in that directory, does not exist. This normally occurs +only when the daemon has unexpectedly died. +The error log file for the printer and the \fIsyslogd\fP logs +should be checked for a +diagnostic from the deceased process. +To restart an \fIlpd\fP, use +.DS +% lpc restart \fIprinter\fP +.DE +.SH +no space on remote; waiting for queue to drain +.IP +This implies that there is insufficient disk space on the remote. +If the file is large enough, there will never be enough space on +the remote (even after the queue on the remote is empty). The solution here +is to move the spooling queue or make more free space on the remote. +.NH 2 +LPRM +.SH +lprm: \fIprinter\fP\|: cannot restart printer daemon +.IP +This case is the same as when +.I lpr +prints that the daemon cannot be started. +.NH 2 +LPD +.PP +The +.I lpd +program can log many different messages using \fIsyslogd\fP\|(8). +Most of these messages are about files that can not +be opened and usually imply that the +.I printcap +file or the protection modes of the files are +incorrect. Files may also be inaccessible if people +manually manipulate the line printer system (i.e. they +bypass the +.I lpr +program). +.PP +In addition to messages generated by +.IR lpd , +any of the filters that +.I lpd +spawns may log messages using \fIsyslogd\fP or to the error log file +(the file specified in the \fBlf\fP entry in \fIprintcap\fP\|). +.NH 2 +LPC +.PP +.SH +couldn't start printer +.IP +This case is the same as when +.I lpr +reports that the daemon cannot be started. +.SH +cannot examine spool directory +.IP +Error messages beginning with ``cannot ...'' are usually because of +incorrect ownership or protection mode of the lock file, spooling +directory or the +.I lpc +program. diff --git a/usr.sbin/lpr/SMM.doc/Makefile b/usr.sbin/lpr/SMM.doc/Makefile new file mode 100644 index 0000000..1701c86 --- /dev/null +++ b/usr.sbin/lpr/SMM.doc/Makefile @@ -0,0 +1,10 @@ +# @(#)Makefile 8.1 (Berkeley) 6/8/93 + +DIR= smm/07.lpd +SRCS= 0.t 1.t 2.t 3.t 4.t 5.t 6.t 7.t +MACROS= -ms + +paper.ps: ${SRCS} + ${TBL} ${SRCS} | ${ROFF} > ${.TARGET} + +.include diff --git a/usr.sbin/lpr/SMM.doc/spell.ok b/usr.sbin/lpr/SMM.doc/spell.ok new file mode 100644 index 0000000..bf31319 --- /dev/null +++ b/usr.sbin/lpr/SMM.doc/spell.ok @@ -0,0 +1,70 @@ +Aprinter +Bprinter +CRMOD +Cprinter +DecWriter +Dprinter +Eprinter +LPC +LPD +Lpd +Manual''SMM:5 +SIGINT +SMM:5 +Topq +XTABS +adm +af +br +daemon +daemons +dev +f:of +fs +hosts.equiv +hosts.lpd +lf +lg +lib +lp:br +lp:sd +lpc +lpd +lpd.lock +lpf +lpf:lf +lprgroup +makefile +mx +offline +pl +printcap +pw +py +rc +rcmd +rg +rlogin +rp +rs +rsh +rshd +rvcat +rvcat:af +rvcat:mx +sd +src +syslogd +tf +topq +ucb +ucbvax +ucbvax:rp +usr.lib +va0:sd +vaacct +vad:of +varian +vaxlpd +vpf +vpf:tf diff --git a/usr.sbin/lpr/common_source/common.c b/usr.sbin/lpr/common_source/common.c new file mode 100644 index 0000000..49f7939 --- /dev/null +++ b/usr.sbin/lpr/common_source/common.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)common.c 8.2 (Berkeley) 1/21/94"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "pathnames.h" + +/* + * Routines and data common to all the line printer functions. + */ + +char *AF; /* accounting file */ +long BR; /* baud rate if lp is a tty */ +char *CF; /* name of cifplot filter (per job) */ +char *DF; /* name of tex filter (per job) */ +long DU; /* daeomon user-id */ +long FC; /* flags to clear if lp is a tty */ +char *FF; /* form feed string */ +long FS; /* flags to set if lp is a tty */ +char *GF; /* name of graph(1G) filter (per job) */ +long HL; /* print header last */ +char *IF; /* name of input filter (created per job) */ +char *LF; /* log file for error messages */ +char *LO; /* lock file name */ +char *LP; /* line printer device name */ +long MC; /* maximum number of copies allowed */ +long MX; /* maximum number of blocks to copy */ +char *NF; /* name of ditroff filter (per job) */ +char *OF; /* name of output filter (created once) */ +char *PF; /* name of vrast filter (per job) */ +long PL; /* page length */ +long PW; /* page width */ +long PX; /* page width in pixels */ +long PY; /* page length in pixels */ +char *RF; /* name of fortran text filter (per job) */ +char *RG; /* resricted group */ +char *RM; /* remote machine name */ +char *RP; /* remote printer name */ +long RS; /* restricted to those with local accounts */ +long RW; /* open LP for reading and writing */ +long SB; /* short banner instead of normal header */ +long SC; /* suppress multiple copies */ +char *SD; /* spool directory */ +long SF; /* suppress FF on each print job */ +long SH; /* suppress header page */ +char *ST; /* status file name */ +char *TF; /* name of troff filter (per job) */ +char *TR; /* trailer string to be output when Q empties */ +char *VF; /* name of vplot filter (per job) */ +long XC; /* flags to clear for local mode */ +long XS; /* flags to set for local mode */ + +char line[BUFSIZ]; +char *bp; /* pointer into printcap buffer. */ +char *name; /* program name */ +char *printer; /* printer name */ + /* host machine name */ +char host[MAXHOSTNAMELEN]; +char *from = host; /* client's machine name */ +int sendtorem; /* are we sending to a remote? */ +char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; + +static int compar __P((const void *, const void *)); + +/* + * Create a connection to the remote printer server. + * Most of this code comes from rcmd.c. + */ +int +getport(rhost) + char *rhost; +{ + struct hostent *hp; + struct servent *sp; + struct sockaddr_in sin; + int s, timo = 1, lport = IPPORT_RESERVED - 1; + int err; + + /* + * Get the host address and port number to connect to. + */ + if (rhost == NULL) + fatal("no remote host to connect to"); + hp = gethostbyname(rhost); + if (hp == NULL) + fatal("unknown host %s", rhost); + sp = getservbyname("printer", "tcp"); + if (sp == NULL) + fatal("printer/tcp: unknown service"); + bzero((char *)&sin, sizeof(sin)); + bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); + sin.sin_family = hp->h_addrtype; + sin.sin_port = sp->s_port; + + /* + * Try connecting to the server. + */ +retry: + s = rresvport(&lport); + if (s < 0) + return(-1); + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + err = errno; + (void) close(s); + errno = err; + if (errno == EADDRINUSE) { + lport--; + goto retry; + } + if (errno == ECONNREFUSED && timo <= 16) { + sleep(timo); + timo *= 2; + goto retry; + } + return(-1); + } + return(s); +} + +/* + * Getline reads a line from the control file cfp, removes tabs, converts + * new-line to null and leaves it in line. + * Returns 0 at EOF or the number of characters read. + */ +int +getline(cfp) + FILE *cfp; +{ + register int linel = 0; + register char *lp = line; + register c; + + while ((c = getc(cfp)) != '\n') { + if (c == EOF) + return(0); + if (c == '\t') { + do { + *lp++ = ' '; + linel++; + } while ((linel & 07) != 0); + continue; + } + *lp++ = c; + linel++; + } + *lp++ = '\0'; + return(linel); +} + +/* + * Scan the current directory and make a list of daemon files sorted by + * creation time. + * Return the number of entries and a pointer to the list. + */ +int +getq(namelist) + struct queue *(*namelist[]); +{ + register struct dirent *d; + register struct queue *q, **queue; + register int nitems; + struct stat stbuf; + DIR *dirp; + int arraysz; + + if ((dirp = opendir(SD)) == NULL) + return(-1); + if (fstat(dirp->dd_fd, &stbuf) < 0) + goto errdone; + + /* + * Estimate the array size by taking the size of the directory file + * and dividing it by a multiple of the minimum size entry. + */ + arraysz = (stbuf.st_size / 24); + queue = (struct queue **)malloc(arraysz * sizeof(struct queue *)); + if (queue == NULL) + goto errdone; + + nitems = 0; + while ((d = readdir(dirp)) != NULL) { + if (d->d_name[0] != 'c' || d->d_name[1] != 'f') + continue; /* daemon control files only */ + if (stat(d->d_name, &stbuf) < 0) + continue; /* Doesn't exist */ + q = (struct queue *)malloc(sizeof(time_t)+strlen(d->d_name)+1); + if (q == NULL) + goto errdone; + q->q_time = stbuf.st_mtime; + strcpy(q->q_name, d->d_name); + /* + * Check to make sure the array has space left and + * realloc the maximum size. + */ + if (++nitems > arraysz) { + queue = (struct queue **)realloc((char *)queue, + (stbuf.st_size/12) * sizeof(struct queue *)); + if (queue == NULL) + goto errdone; + } + queue[nitems-1] = q; + } + closedir(dirp); + if (nitems) + qsort(queue, nitems, sizeof(struct queue *), compar); + *namelist = queue; + return(nitems); + +errdone: + closedir(dirp); + return(-1); +} + +/* + * Compare modification times. + */ +static int +compar(p1, p2) + const void *p1, *p2; +{ + if ((*(struct queue **)p1)->q_time < (*(struct queue **)p2)->q_time) + return(-1); + if ((*(struct queue **)p1)->q_time > (*(struct queue **)p2)->q_time) + return(1); + return(0); +} + +/* + * Figure out whether the local machine is the same + * as the remote machine (RM) entry (if it exists). + */ +char * +checkremote() +{ + char name[MAXHOSTNAMELEN]; + register struct hostent *hp; + static char errbuf[128]; + + sendtorem = 0; /* assume printer is local */ + if (RM != (char *)NULL) { + /* get the official name of the local host */ + gethostname(name, sizeof(name)); + name[sizeof(name)-1] = '\0'; + hp = gethostbyname(name); + if (hp == (struct hostent *) NULL) { + (void) snprintf(errbuf, sizeof(errbuf), + "unable to get official name for local machine %s", + name); + return errbuf; + } else (void) strcpy(name, hp->h_name); + + /* get the official name of RM */ + hp = gethostbyname(RM); + if (hp == (struct hostent *) NULL) { + (void) snprintf(errbuf, sizeof(errbuf), + "unable to get official name for remote machine %s", + RM); + return errbuf; + } + + /* + * if the two hosts are not the same, + * then the printer must be remote. + */ + if (strcmp(name, hp->h_name) != 0) + sendtorem = 1; + } + return (char *)0; +} + +#if __STDC__ +#include +#else +#include +#endif + +void +#if __STDC__ +fatal(const char *msg, ...) +#else +fatal(msg, va_alist) + char *msg; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, msg); +#else + va_start(ap); +#endif + if (from != host) + (void)printf("%s: ", host); + (void)printf("%s: ", name); + if (printer) + (void)printf("%s: ", printer); + (void)vprintf(msg, ap); + va_end(ap); + (void)putchar('\n'); + exit(1); +} diff --git a/usr.sbin/lpr/common_source/displayq.c b/usr.sbin/lpr/common_source/displayq.c new file mode 100644 index 0000000..59d3cc9 --- /dev/null +++ b/usr.sbin/lpr/common_source/displayq.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)displayq.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "lp.local.h" +#include "pathnames.h" + +/* + * Routines to display the state of the queue. + */ +#define JOBCOL 40 /* column for job # in -l format */ +#define OWNCOL 7 /* start of Owner column in normal */ +#define SIZCOL 62 /* start of Size column in normal */ + +/* + * Stuff for handling job specifications + */ +extern int requ[]; /* job number of spool entries */ +extern int requests; /* # of spool requests */ +extern char *user[]; /* users to process */ +extern int users; /* # of users in user array */ + +static int col; /* column on screen */ +static char current[40]; /* current file being printed */ +static char file[132]; /* print file name */ +static int first; /* first file in ``files'' column? */ +static int garbage; /* # of garbage cf files */ +static int lflag; /* long output option */ +static int rank; /* order to be printed (-1=none, 0=active) */ +static long totsize; /* total print job size in bytes */ + +static char *head0 = "Rank Owner Job Files"; +static char *head1 = "Total Size\n"; + +/* + * Display the current state of the queue. Format = 1 if long format. + */ +void +displayq(format) + int format; +{ + register struct queue *q; + register int i, nitems, fd; + register char *cp; + struct queue **queue; + struct stat statb; + FILE *fp; + + lflag = format; + totsize = 0; + rank = -1; + if ((i = cgetent(&bp, printcapdb, printer)) == -2) + fatal("can't open printer description file"); + else if (i == -1) + fatal("unknown printer"); + else if (i == -3) + fatal("potential reference loop detected in printcap file"); + if (cgetstr(bp, "lp", &LP) < 0) + LP = _PATH_DEFDEVLP; + if (cgetstr(bp, "rp", &RP) < 0) + RP = DEFLP; + if (cgetstr(bp, "sd", &SD) < 0) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp,"lo", &LO) < 0) + LO = DEFLOCK; + if (cgetstr(bp, "st", &ST) < 0) + ST = DEFSTAT; + cgetstr(bp, "rm", &RM); + if (cp = checkremote()) + printf("Warning: %s\n", cp); + + /* + * Print out local queue + * Find all the control files in the spooling directory + */ + if (chdir(SD) < 0) + fatal("cannot chdir to spooling directory"); + if ((nitems = getq(&queue)) < 0) + fatal("cannot examine spooling area\n"); + if (stat(LO, &statb) >= 0) { + if (statb.st_mode & 0100) { + if (sendtorem) + printf("%s: ", host); + printf("Warning: %s is down: ", printer); + fd = open(ST, O_RDONLY); + if (fd >= 0) { + (void) flock(fd, LOCK_SH); + while ((i = read(fd, line, sizeof(line))) > 0) + (void) fwrite(line, 1, i, stdout); + (void) close(fd); /* unlocks as well */ + } else + putchar('\n'); + } + if (statb.st_mode & 010) { + if (sendtorem) + printf("%s: ", host); + printf("Warning: %s queue is turned off\n", printer); + } + } + + if (nitems) { + fp = fopen(LO, "r"); + if (fp == NULL) + warn(); + else { + /* get daemon pid */ + cp = current; + while ((*cp = getc(fp)) != EOF && *cp != '\n') + cp++; + *cp = '\0'; + i = atoi(current); + if (i <= 0 || kill(i, 0) < 0) + warn(); + else { + /* read current file name */ + cp = current; + while ((*cp = getc(fp)) != EOF && *cp != '\n') + cp++; + *cp = '\0'; + /* + * Print the status file. + */ + if (sendtorem) + printf("%s: ", host); + fd = open(ST, O_RDONLY); + if (fd >= 0) { + (void) flock(fd, LOCK_SH); + while ((i = read(fd, line, sizeof(line))) > 0) + (void) fwrite(line, 1, i, stdout); + (void) close(fd); /* unlocks as well */ + } else + putchar('\n'); + } + (void) fclose(fp); + } + /* + * Now, examine the control files and print out the jobs to + * be done for each user. + */ + if (!lflag) + header(); + for (i = 0; i < nitems; i++) { + q = queue[i]; + inform(q->q_name); + free(q); + } + free(queue); + } + if (!sendtorem) { + if (nitems == 0) + puts("no entries"); + return; + } + + /* + * Print foreign queue + * Note that a file in transit may show up in either queue. + */ + if (nitems) + putchar('\n'); + (void) sprintf(line, "%c%s", format + '\3', RP); + cp = line; + for (i = 0; i < requests; i++) { + cp += strlen(cp); + (void) sprintf(cp, " %d", requ[i]); + } + for (i = 0; i < users; i++) { + cp += strlen(cp); + *cp++ = ' '; + (void) strcpy(cp, user[i]); + } + strcat(line, "\n"); + fd = getport(RM); + if (fd < 0) { + if (from != host) + printf("%s: ", host); + printf("connection to %s is down\n", RM); + } + else { + i = strlen(line); + if (write(fd, line, i) != i) + fatal("Lost connection"); + while ((i = read(fd, line, sizeof(line))) > 0) + (void) fwrite(line, 1, i, stdout); + (void) close(fd); + } +} + +/* + * Print a warning message if there is no daemon present. + */ +void +warn() +{ + if (sendtorem) + printf("\n%s: ", host); + puts("Warning: no daemon present"); + current[0] = '\0'; +} + +/* + * Print the header for the short listing format + */ +void +header() +{ + printf(head0); + col = strlen(head0)+1; + blankfill(SIZCOL); + printf(head1); +} + +void +inform(cf) + char *cf; +{ + register int j; + FILE *cfp; + + /* + * There's a chance the control file has gone away + * in the meantime; if this is the case just keep going + */ + if ((cfp = fopen(cf, "r")) == NULL) + return; + + if (rank < 0) + rank = 0; + if (sendtorem || garbage || strcmp(cf, current)) + rank++; + j = 0; + while (getline(cfp)) { + switch (line[0]) { + case 'P': /* Was this file specified in the user's list? */ + if (!inlist(line+1, cf)) { + fclose(cfp); + return; + } + if (lflag) { + printf("\n%s: ", line+1); + col = strlen(line+1) + 2; + prank(rank); + blankfill(JOBCOL); + printf(" [job %s]\n", cf+3); + } else { + col = 0; + prank(rank); + blankfill(OWNCOL); + printf("%-10s %-3d ", line+1, atoi(cf+3)); + col += 16; + first = 1; + } + continue; + default: /* some format specifer and file name? */ + if (line[0] < 'a' || line[0] > 'z') + continue; + if (j == 0 || strcmp(file, line+1) != 0) + (void) strcpy(file, line+1); + j++; + continue; + case 'N': + show(line+1, file, j); + file[0] = '\0'; + j = 0; + } + } + fclose(cfp); + if (!lflag) { + blankfill(SIZCOL); + printf("%ld bytes\n", totsize); + totsize = 0; + } +} + +int +inlist(name, file) + char *name, *file; +{ + register int *r, n; + register char **u, *cp; + + if (users == 0 && requests == 0) + return(1); + /* + * Check to see if it's in the user list + */ + for (u = user; u < &user[users]; u++) + if (!strcmp(*u, name)) + return(1); + /* + * Check the request list + */ + for (n = 0, cp = file+3; isdigit(*cp); ) + n = n * 10 + (*cp++ - '0'); + for (r = requ; r < &requ[requests]; r++) + if (*r == n && !strcmp(cp, from)) + return(1); + return(0); +} + +void +show(nfile, file, copies) + register char *nfile, *file; + int copies; +{ + if (strcmp(nfile, " ") == 0) + nfile = "(standard input)"; + if (lflag) + ldump(nfile, file, copies); + else + dump(nfile, file, copies); +} + +/* + * Fill the line with blanks to the specified column + */ +void +blankfill(n) + register int n; +{ + while (col++ < n) + putchar(' '); +} + +/* + * Give the abbreviated dump of the file names + */ +void +dump(nfile, file, copies) + char *nfile, *file; + int copies; +{ + register short n, fill; + struct stat lbuf; + + /* + * Print as many files as will fit + * (leaving room for the total size) + */ + fill = first ? 0 : 2; /* fill space for ``, '' */ + if (((n = strlen(nfile)) + col + fill) >= SIZCOL-4) { + if (col < SIZCOL) { + printf(" ..."), col += 4; + blankfill(SIZCOL); + } + } else { + if (first) + first = 0; + else + printf(", "); + printf("%s", nfile); + col += n+fill; + } + if (*file && !stat(file, &lbuf)) + totsize += copies * lbuf.st_size; +} + +/* + * Print the long info about the file + */ +void +ldump(nfile, file, copies) + char *nfile, *file; + int copies; +{ + struct stat lbuf; + + putchar('\t'); + if (copies > 1) + printf("%-2d copies of %-19s", copies, nfile); + else + printf("%-32s", nfile); + if (*file && !stat(file, &lbuf)) + printf(" %qd bytes", lbuf.st_size); + else + printf(" ??? bytes"); + putchar('\n'); +} + +/* + * Print the job's rank in the queue, + * update col for screen management + */ +void +prank(n) + int n; +{ + char rline[100]; + static char *r[] = { + "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" + }; + + if (n == 0) { + printf("active"); + col += 6; + return; + } + if ((n/10)%10 == 1) + (void)snprintf(rline, sizeof(rline), "%dth", n); + else + (void)snprintf(rline, sizeof(rline), "%d%s", n, r[n%10]); + col += strlen(rline); + printf("%s", rline); +} diff --git a/usr.sbin/lpr/common_source/lp.h b/usr.sbin/lpr/common_source/lp.h new file mode 100644 index 0000000..6dd1bf0 --- /dev/null +++ b/usr.sbin/lpr/common_source/lp.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)lp.h 8.1 (Berkeley) 6/6/93 + */ + + +/* + * Global definitions for the line printer system. + */ + +extern char *AF; /* accounting file */ +extern long BR; /* baud rate if lp is a tty */ +extern char *CF; /* name of cifplot filter (per job) */ +extern char *DF; /* name of tex filter (per job) */ +extern long DU; /* daeomon user-id */ +extern long FC; /* flags to clear if lp is a tty */ +extern char *FF; /* form feed string */ +extern long FS; /* flags to set if lp is a tty */ +extern char *GF; /* name of graph(1G) filter (per job) */ +extern long HL; /* print header last */ +extern char *IF; /* name of input filter (created per job) */ +extern char *LF; /* log file for error messages */ +extern char *LO; /* lock file name */ +extern char *LP; /* line printer device name */ +extern long MC; /* maximum number of copies allowed */ +extern long MX; /* maximum number of blocks to copy */ +extern char *NF; /* name of ditroff(1) filter (per job) */ +extern char *OF; /* name of output filter (created once) */ +extern long PL; /* page length */ +extern long PW; /* page width */ +extern long PX; /* page width in pixels */ +extern long PY; /* page length in pixels */ +extern char *RF; /* name of fortran text filter (per job) */ +extern char *RG; /* restricted group */ +extern char *RM; /* remote machine name */ +extern char *RP; /* remote printer name */ +extern long RS; /* restricted to those with local accounts */ +extern long RW; /* open LP for reading and writing */ +extern long SB; /* short banner instead of normal header */ +extern long SC; /* suppress multiple copies */ +extern char *SD; /* spool directory */ +extern long SF; /* suppress FF on each print job */ +extern long SH; /* suppress header page */ +extern char *ST; /* status file name */ +extern char *TF; /* name of troff(1) filter (per job) */ +extern char *TR; /* trailer string to be output when Q empties */ +extern char *VF; /* name of raster filter (per job) */ +extern long XC; /* flags to clear for local mode */ +extern long XS; /* flags to set for local mode */ + +extern char line[BUFSIZ]; +extern char *bp; /* pointer into printcap buffer */ +extern char *name; /* program name */ +extern char *printer; /* printer name */ + /* host machine name */ +extern char host[MAXHOSTNAMELEN]; +extern char *from; /* client's machine name */ +extern int sendtorem; /* are we sending to a remote? */ +extern char *printcapdb[]; /* printcap database array */ +/* + * Structure used for building a sorted list of control files. + */ +struct queue { + time_t q_time; /* modification time */ + char q_name[MAXNAMLEN+1]; /* control file name */ +}; + +#include + +__BEGIN_DECLS +struct dirent; + +void blankfill __P((int)); +char *checkremote __P((void)); +int chk __P((char *)); +void displayq __P((int)); +void dump __P((char *, char *, int)); +void fatal __P((const char *, ...)); +int getline __P((FILE *)); +int getport __P((char *)); +int getq __P((struct queue *(*[]))); +void header __P((void)); +void inform __P((char *)); +int inlist __P((char *, char *)); +int iscf __P((struct dirent *)); +int isowner __P((char *, char *)); +void ldump __P((char *, char *, int)); +int lockchk __P((char *)); +void prank __P((int)); +void process __P((char *)); +void rmjob __P((void)); +void rmremote __P((void)); +void show __P((char *, char *, int)); +int startdaemon __P((char *)); +void warn __P((void)); +__END_DECLS diff --git a/usr.sbin/lpr/common_source/lp.local.h b/usr.sbin/lpr/common_source/lp.local.h new file mode 100644 index 0000000..837fd2f --- /dev/null +++ b/usr.sbin/lpr/common_source/lp.local.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)lp.local.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Possibly, local parameters to the spooling system + */ + +/* + * Defaults for line printer capabilities data base + */ +#define DEFLP "lp" +#define DEFLOCK "lock" +#define DEFSTAT "status" +#define DEFMX 1000 +#define DEFMAXCOPIES 0 +#define DEFFF "\f" +#define DEFWIDTH 132 +#define DEFLENGTH 66 +#define DEFUID 1 + +/* + * When files are created in the spooling area, they are normally + * readable only by their owner and the spooling group. If you + * want otherwise, change this mode. + */ +#define FILMOD 0660 + +/* + * Printer is assumed to support LINELEN (for block chars) + * and background character (blank) is a space + */ +#define LINELEN 132 +#define BACKGND ' ' + +#define HEIGHT 9 /* height of characters */ +#define WIDTH 8 /* width of characters */ +#define DROP 3 /* offset to drop characters with descenders */ + +/* + * Define TERMCAP if the terminal capabilites are to be used for lpq. + */ +#define TERMCAP + +/* + * Maximum number of user and job requests for lpq and lprm. + */ +#define MAXUSERS 50 +#define MAXREQUESTS 50 diff --git a/usr.sbin/lpr/common_source/pathnames.h b/usr.sbin/lpr/common_source/pathnames.h new file mode 100644 index 0000000..5c07cdb --- /dev/null +++ b/usr.sbin/lpr/common_source/pathnames.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#include + +#define _PATH_DEFDEVLP "/dev/lp" +#define _PATH_DEFSPOOL "/var/spool/output/lpd" +#define _PATH_HOSTSEQUIV "/etc/hosts.equiv" +#define _PATH_HOSTSLPD "/etc/hosts.lpd" +#define _PATH_MASTERLOCK "/var/spool/output/lpd.lock" +#define _PATH_PR "/usr/bin/pr" +#define _PATH_PRINTCAP "/etc/printcap" +#define _PATH_SOCKETNAME "/var/run/printer" +#define _PATH_VFONT "/usr/libdata/vfont/" +#define _PATH_VFONTB "/usr/libdata/vfont/B" +#define _PATH_VFONTI "/usr/libdata/vfont/I" +#define _PATH_VFONTR "/usr/libdata/vfont/R" +#define _PATH_VFONTS "/usr/libdata/vfont/S" diff --git a/usr.sbin/lpr/common_source/printcap.c b/usr.sbin/lpr/common_source/printcap.c new file mode 100644 index 0000000..627d2ce --- /dev/null +++ b/usr.sbin/lpr/common_source/printcap.c @@ -0,0 +1,458 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)printcap.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include + +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "pathnames.h" + +#ifndef BUFSIZ +#define BUFSIZ 1024 +#endif +#define MAXHOP 32 /* max number of tc= indirections */ + +/* + * termcap - routines for dealing with the terminal capability data base + * + * BUG: Should use a "last" pointer in tbuf, so that searching + * for capabilities alphabetically would not be a n**2/2 + * process when large numbers of capabilities are given. + * Note: If we add a last pointer now we will screw up the + * tc capability. We really should compile termcap. + * + * Essentially all the work here is scanning and decoding escapes + * in string capabilities. We don't use stdio because the editor + * doesn't, and because living w/o it is not hard. + */ + +#define PRINTCAP + +#ifdef PRINTCAP +#define tgetent pgetent +#define tskip pskip +#define tgetstr pgetstr +#define tdecode pdecode +#define tgetnum pgetnum +#define tgetflag pgetflag +#define tdecode pdecode +#define tnchktc pnchktc +#define tnamatch pnamatch +#define V6 +#endif + +static FILE *pfp = NULL; /* printcap data base file pointer */ +static char *tbuf; +static int hopcount; /* detect infinite loops in termcap, init 0 */ + +static char *tskip __P((char *)); +static char *tskip __P((char *bp)); +static char *tdecode __P((char *, char **)); + +/* + * Similar to tgetent except it returns the next enrty instead of + * doing a lookup. + */ +int +getprent(bp) + register char *bp; +{ + register int c, skip = 0; + + if (pfp == NULL && (pfp = fopen(_PATH_PRINTCAP, "r")) == NULL) + return(-1); + tbuf = bp; + for (;;) { + switch (c = getc(pfp)) { + case EOF: + fclose(pfp); + pfp = NULL; + return(0); + case '\n': + if (bp == tbuf) { + skip = 0; + continue; + } + if (bp[-1] == '\\') { + bp--; + continue; + } + *bp = '\0'; + return(1); + case '#': + if (bp == tbuf) + skip++; + default: + if (skip) + continue; + if (bp >= tbuf+BUFSIZ) { + write(2, "Termcap entry too long\n", 23); + *bp = '\0'; + return(1); + } + *bp++ = c; + } + } +} + +void +endprent() +{ + if (pfp != NULL) + fclose(pfp); +} + +/* + * Get an entry for terminal name in buffer bp, + * from the termcap file. Parse is very rudimentary; + * we just notice escaped newlines. + */ +int +tgetent(bp, name) + char *bp, *name; +{ + register char *cp; + register int c; + register int i = 0, cnt = 0; + char ibuf[BUFSIZ]; + int tf; + + tbuf = bp; + tf = 0; +#ifndef V6 + cp = getenv("TERMCAP"); + /* + * TERMCAP can have one of two things in it. It can be the + * name of a file to use instead of /etc/termcap. In this + * case it better start with a "/". Or it can be an entry to + * use so we don't have to read the file. In this case it + * has to already have the newlines crunched out. + */ + if (cp && *cp) { + if (*cp!='/') { + cp2 = getenv("TERM"); + if (cp2==(char *) 0 || strcmp(name,cp2)==0) { + strcpy(bp,cp); + return(tnchktc()); + } else { + tf = open(_PATH_PRINTCAP, 0); + } + } else + tf = open(cp, 0); + } + if (tf==0) + tf = open(_PATH_PRINTCAP, 0); +#else + tf = open(_PATH_PRINTCAP, 0); +#endif + if (tf < 0) + return (-1); + for (;;) { + cp = bp; + for (;;) { + if (i == cnt) { + cnt = read(tf, ibuf, BUFSIZ); + if (cnt <= 0) { + close(tf); + return (0); + } + i = 0; + } + c = ibuf[i++]; + if (c == '\n') { + if (cp > bp && cp[-1] == '\\'){ + cp--; + continue; + } + break; + } + if (cp >= bp+BUFSIZ) { + write(2,"Termcap entry too long\n", 23); + break; + } else + *cp++ = c; + } + *cp = 0; + + /* + * The real work for the match. + */ + if (tnamatch(name)) { + close(tf); + return(tnchktc()); + } + } +} + +/* + * tnchktc: check the last entry, see if it's tc=xxx. If so, + * recursively find xxx and append that entry (minus the names) + * to take the place of the tc=xxx entry. This allows termcap + * entries to say "like an HP2621 but doesn't turn on the labels". + * Note that this works because of the left to right scan. + */ +int +tnchktc() +{ + register char *p, *q; + char tcname[16]; /* name of similar terminal */ + char tcbuf[BUFSIZ]; + char *holdtbuf = tbuf; + int l; + + p = tbuf + strlen(tbuf) - 2; /* before the last colon */ + while (*--p != ':') + if (p MAXHOP) { + write(2, "Infinite tc= loop\n", 18); + return (0); + } + if (tgetent(tcbuf, tcname) != 1) + return(0); + for (q=tcbuf; *q != ':'; q++) + ; + l = p - holdtbuf + strlen(q); + if (l > BUFSIZ) { + write(2, "Termcap entry too long\n", 23); + q[BUFSIZ - (p-tbuf)] = 0; + } + strcpy(p, q+1); + tbuf = holdtbuf; + return(1); +} + +/* + * Tnamatch deals with name matching. The first field of the termcap + * entry is a sequence of names separated by |'s, so we compare + * against each such name. The normal : terminator after the last + * name (before the first field) stops us. + */ +int +tnamatch(np) + char *np; +{ + register char *Np, *Bp; + + Bp = tbuf; + if (*Bp == '#') + return(0); + for (;;) { + for (Np = np; *Np && *Bp == *Np; Bp++, Np++) + continue; + if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) + return (1); + while (*Bp && *Bp != ':' && *Bp != '|') + Bp++; + if (*Bp == 0 || *Bp == ':') + return (0); + Bp++; + } +} + +/* + * Skip to the next field. Notice that this is very dumb, not + * knowing about \: escapes or any such. If necessary, :'s can be put + * into the termcap file in octal. + */ +static char * +tskip(bp) + register char *bp; +{ + + while (*bp && *bp != ':') + bp++; + if (*bp == ':') + bp++; + return (bp); +} + +/* + * Return the (numeric) option id. + * Numeric options look like + * li#80 + * i.e. the option string is separated from the numeric value by + * a # character. If the option is not found we return -1. + * Note that we handle octal numbers beginning with 0. + */ +int +tgetnum(id) + char *id; +{ + register int i, base; + register char *bp = tbuf; + + for (;;) { + bp = tskip(bp); + if (*bp == 0) + return (-1); + if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) + continue; + if (*bp == '@') + return(-1); + if (*bp != '#') + continue; + bp++; + base = 10; + if (*bp == '0') + base = 8; + i = 0; + while (isdigit(*bp)) + i *= base, i += *bp++ - '0'; + return (i); + } +} + +/* + * Handle a flag option. + * Flag options are given "naked", i.e. followed by a : or the end + * of the buffer. Return 1 if we find the option, or 0 if it is + * not given. + */ +int +tgetflag(id) + char *id; +{ + register char *bp = tbuf; + + for (;;) { + bp = tskip(bp); + if (!*bp) + return (0); + if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { + if (!*bp || *bp == ':') + return (1); + else if (*bp == '@') + return(0); + } + } +} + +/* + * Get a string valued option. + * These are given as + * cl=^Z + * Much decoding is done on the strings, and the strings are + * placed in area, which is a ref parameter which is updated. + * No checking on area overflow. + */ +char * +tgetstr(id, area) + char *id, **area; +{ + register char *bp = tbuf; + + for (;;) { + bp = tskip(bp); + if (!*bp) + return (0); + if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) + continue; + if (*bp == '@') + return(0); + if (*bp != '=') + continue; + bp++; + return (tdecode(bp, area)); + } +} + +/* + * Tdecode does the grung work to decode the + * string capability escapes. + */ +static char * +tdecode(str, area) + register char *str; + char **area; +{ + register char *cp; + register int c; + register char *dp; + int i; + + cp = *area; + while ((c = *str++) && c != ':') { + switch (c) { + + case '^': + c = *str++ & 037; + break; + + case '\\': + dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; + c = *str++; +nextc: + if (*dp++ == c) { + c = *dp++; + break; + } + dp++; + if (*dp) + goto nextc; + if (isdigit(c)) { + c -= '0', i = 2; + do + c <<= 3, c |= *str++ - '0'; + while (--i && isdigit(*str)); + } + break; + } + *cp++ = c; + } + *cp++ = 0; + str = *area; + *area = cp; + return (str); +} + diff --git a/usr.sbin/lpr/common_source/rmjob.c b/usr.sbin/lpr/common_source/rmjob.c new file mode 100644 index 0000000..74a94d8 --- /dev/null +++ b/usr.sbin/lpr/common_source/rmjob.c @@ -0,0 +1,339 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)rmjob.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "lp.local.h" +#include "pathnames.h" + +/* + * rmjob - remove the specified jobs from the queue. + */ + +/* + * Stuff for handling lprm specifications + */ +extern char *user[]; /* users to process */ +extern int users; /* # of users in user array */ +extern int requ[]; /* job number of spool entries */ +extern int requests; /* # of spool requests */ +extern char *person; /* name of person doing lprm */ + +static char root[] = "root"; +static int all = 0; /* eliminate all files (root only) */ +static int cur_daemon; /* daemon's pid */ +static char current[40]; /* active control file name */ + +void +rmjob() +{ + register int i, nitems; + int assasinated = 0; + struct dirent **files; + char *cp; + + if ((i = cgetent(&bp, printcapdb, printer)) == -2) + fatal("can't open printer description file"); + else if (i == -1) + fatal("unknown printer"); + else if (i == -3) + fatal("potential reference loop detected in printcap file"); + if (cgetstr(bp, "lp", &LP) < 0) + LP = _PATH_DEFDEVLP; + if (cgetstr(bp, "rp", &RP) < 0) + RP = DEFLP; + if (cgetstr(bp, "sd", &SD) < 0) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp,"lo", &LO) < 0) + LO = DEFLOCK; + cgetstr(bp, "rm", &RM); + if (cp = checkremote()) + printf("Warning: %s\n", cp); + + /* + * If the format was `lprm -' and the user isn't the super-user, + * then fake things to look like he said `lprm user'. + */ + if (users < 0) { + if (getuid() == 0) + all = 1; /* all files in local queue */ + else { + user[0] = person; + users = 1; + } + } + if (!strcmp(person, "-all")) { + if (from == host) + fatal("The login name \"-all\" is reserved"); + all = 1; /* all those from 'from' */ + person = root; + } + + if (chdir(SD) < 0) + fatal("cannot chdir to spool directory"); + if ((nitems = scandir(".", &files, iscf, NULL)) < 0) + fatal("cannot access spool directory"); + + if (nitems) { + /* + * Check for an active printer daemon (in which case we + * kill it if it is reading our file) then remove stuff + * (after which we have to restart the daemon). + */ + if (lockchk(LO) && chk(current)) { + assasinated = kill(cur_daemon, SIGINT) == 0; + if (!assasinated) + fatal("cannot kill printer daemon"); + } + /* + * process the files + */ + for (i = 0; i < nitems; i++) + process(files[i]->d_name); + } + rmremote(); + /* + * Restart the printer daemon if it was killed + */ + if (assasinated && !startdaemon(printer)) + fatal("cannot restart printer daemon\n"); + exit(0); +} + +/* + * Process a lock file: collect the pid of the active + * daemon and the file name of the active spool entry. + * Return boolean indicating existence of a lock file. + */ +int +lockchk(s) + char *s; +{ + register FILE *fp; + register int i, n; + + if ((fp = fopen(s, "r")) == NULL) + if (errno == EACCES) + fatal("can't access lock file"); + else + return(0); + if (!getline(fp)) { + (void) fclose(fp); + return(0); /* no daemon present */ + } + cur_daemon = atoi(line); + if (kill(cur_daemon, 0) < 0) { + (void) fclose(fp); + return(0); /* no daemon present */ + } + for (i = 1; (n = fread(current, sizeof(char), sizeof(current), fp)) <= 0; i++) { + if (i > 5) { + n = 1; + break; + } + sleep(i); + } + current[n-1] = '\0'; + (void) fclose(fp); + return(1); +} + +/* + * Process a control file. + */ +void +process(file) + char *file; +{ + FILE *cfp; + + if (!chk(file)) + return; + if ((cfp = fopen(file, "r")) == NULL) + fatal("cannot open %s", file); + while (getline(cfp)) { + switch (line[0]) { + case 'U': /* unlink associated files */ + if (from != host) + printf("%s: ", host); + printf(unlink(line+1) ? "cannot dequeue %s\n" : + "%s dequeued\n", line+1); + } + } + (void) fclose(cfp); + if (from != host) + printf("%s: ", host); + printf(unlink(file) ? "cannot dequeue %s\n" : "%s dequeued\n", file); +} + +/* + * Do the dirty work in checking + */ +int +chk(file) + char *file; +{ + register int *r, n; + register char **u, *cp; + FILE *cfp; + + /* + * Check for valid cf file name (mostly checking current). + */ + if (strlen(file) < 7 || file[0] != 'c' || file[1] != 'f') + return(0); + + if (all && (from == host || !strcmp(from, file+6))) + return(1); + + /* + * get the owner's name from the control file. + */ + if ((cfp = fopen(file, "r")) == NULL) + return(0); + while (getline(cfp)) { + if (line[0] == 'P') + break; + } + (void) fclose(cfp); + if (line[0] != 'P') + return(0); + + if (users == 0 && requests == 0) + return(!strcmp(file, current) && isowner(line+1, file)); + /* + * Check the request list + */ + for (n = 0, cp = file+3; isdigit(*cp); ) + n = n * 10 + (*cp++ - '0'); + for (r = requ; r < &requ[requests]; r++) + if (*r == n && isowner(line+1, file)) + return(1); + /* + * Check to see if it's in the user list + */ + for (u = user; u < &user[users]; u++) + if (!strcmp(*u, line+1) && isowner(line+1, file)) + return(1); + return(0); +} + +/* + * If root is removing a file on the local machine, allow it. + * If root is removing a file from a remote machine, only allow + * files sent from the remote machine to be removed. + * Normal users can only remove the file from where it was sent. + */ +int +isowner(owner, file) + char *owner, *file; +{ + if (!strcmp(person, root) && (from == host || !strcmp(from, file+6))) + return(1); + if (!strcmp(person, owner) && !strcmp(from, file+6)) + return(1); + if (from != host) + printf("%s: ", host); + printf("%s: Permission denied\n", file); + return(0); +} + +/* + * Check to see if we are sending files to a remote machine. If we are, + * then try removing files on the remote machine. + */ +void +rmremote() +{ + register char *cp; + register int i, rem; + char buf[BUFSIZ]; + + if (!sendtorem) + return; /* not sending to a remote machine */ + + /* + * Flush stdout so the user can see what has been deleted + * while we wait (possibly) for the connection. + */ + fflush(stdout); + + (void)snprintf(buf, sizeof(buf), "\5%s %s", RP, all ? "-all" : person); + cp = buf; + for (i = 0; i < users; i++) { + cp += strlen(cp); + *cp++ = ' '; + strcpy(cp, user[i]); + } + for (i = 0; i < requests; i++) { + cp += strlen(cp); + (void) sprintf(cp, " %d", requ[i]); + } + strcat(cp, "\n"); + rem = getport(RM); + if (rem < 0) { + if (from != host) + printf("%s: ", host); + printf("connection to %s is down\n", RM); + } else { + i = strlen(buf); + if (write(rem, buf, i) != i) + fatal("Lost connection"); + while ((i = read(rem, buf, sizeof(buf))) > 0) + (void) fwrite(buf, 1, i, stdout); + (void) close(rem); + } +} + +/* + * Return 1 if the filename begins with 'cf' + */ +int +iscf(d) + struct dirent *d; +{ + return(d->d_name[0] == 'c' && d->d_name[1] == 'f'); +} diff --git a/usr.sbin/lpr/common_source/startdaemon.c b/usr.sbin/lpr/common_source/startdaemon.c new file mode 100644 index 0000000..237769e --- /dev/null +++ b/usr.sbin/lpr/common_source/startdaemon.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1983, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)startdaemon.c 8.2 (Berkeley) 4/17/94"; +#endif /* not lint */ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include "lp.h" +#include "pathnames.h" + +static void perr __P((char *)); + +/* + * Tell the printer daemon that there are new files in the spool directory. + */ + +int +startdaemon(printer) + char *printer; +{ + struct sockaddr_un un; + register int s, n; + char buf[BUFSIZ]; + + s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) { + perr("socket"); + return(0); + } + memset(&un, 0, sizeof(un)); + un.sun_family = AF_UNIX; + strcpy(un.sun_path, _PATH_SOCKETNAME); +#ifndef SUN_LEN +#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2) +#endif + if (connect(s, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) { + perr("connect"); + (void) close(s); + return(0); + } + (void) sprintf(buf, "\1%s\n", printer); + n = strlen(buf); + if (write(s, buf, n) != n) { + perr("write"); + (void) close(s); + return(0); + } + if (read(s, buf, 1) == 1) { + if (buf[0] == '\0') { /* everything is OK */ + (void) close(s); + return(1); + } + putchar(buf[0]); + } + while ((n = read(s, buf, sizeof(buf))) > 0) + fwrite(buf, 1, n, stdout); + (void) close(s); + return(0); +} + +static void +perr(msg) + char *msg; +{ + extern char *name; + + (void)printf("%s: %s: %s\n", name, msg, strerror(errno)); +} diff --git a/usr.sbin/lpr/filters/Makefile b/usr.sbin/lpr/filters/Makefile new file mode 100644 index 0000000..c9d5c4f --- /dev/null +++ b/usr.sbin/lpr/filters/Makefile @@ -0,0 +1,7 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= lpf +NOMAN= noman +BINDIR= /usr/libexec/lpr + +.include diff --git a/usr.sbin/lpr/filters/lpf.c b/usr.sbin/lpr/filters/lpf.c new file mode 100644 index 0000000..5335f31 --- /dev/null +++ b/usr.sbin/lpr/filters/lpf.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)lpf.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * filter which reads the output of nroff and converts lines + * with ^H's to overwritten lines. Thus this works like 'ul' + * but is much better: it can handle more than 2 overwrites + * and it is written with some style. + * modified by kls to use register references instead of arrays + * to try to gain a little speed. + */ + +#include +#include +#include +#include + +#define MAXWIDTH 132 +#define MAXREP 10 + +char buf[MAXREP][MAXWIDTH]; +int maxcol[MAXREP] = {-1}; +int lineno; +int width = 132; /* default line length */ +int length = 66; /* page length */ +int indent; /* indentation length */ +int npages = 1; +int literal; /* print control characters */ +char *name; /* user's login name */ +char *host; /* user's machine name */ +char *acctfile; /* accounting information file */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + register FILE *p = stdin, *o = stdout; + register int i, col; + register char *cp; + int done, linedone, maxrep; + char ch, *limit; + + while (--argc) { + if (*(cp = *++argv) == '-') { + switch (cp[1]) { + case 'n': + argc--; + name = *++argv; + break; + + case 'h': + argc--; + host = *++argv; + break; + + case 'w': + if ((i = atoi(&cp[2])) > 0 && i <= MAXWIDTH) + width = i; + break; + + case 'l': + length = atoi(&cp[2]); + break; + + case 'i': + indent = atoi(&cp[2]); + break; + + case 'c': /* Print control chars */ + literal++; + break; + } + } else + acctfile = cp; + } + + for (cp = buf[0], limit = buf[MAXREP]; cp < limit; *cp++ = ' '); + done = 0; + + while (!done) { + col = indent; + maxrep = -1; + linedone = 0; + while (!linedone) { + switch (ch = getc(p)) { + case EOF: + linedone = done = 1; + ch = '\n'; + break; + + case '\f': + lineno = length; + case '\n': + if (maxrep < 0) + maxrep = 0; + linedone = 1; + break; + + case '\b': + if (--col < indent) + col = indent; + break; + + case '\r': + col = indent; + break; + + case '\t': + col = ((col - indent) | 07) + indent + 1; + break; + + case '\031': + /* + * lpd needs to use a different filter to + * print data so stop what we are doing and + * wait for lpd to restart us. + */ + if ((ch = getchar()) == '\1') { + fflush(stdout); + kill(getpid(), SIGSTOP); + break; + } else { + ungetc(ch, stdin); + ch = '\031'; + } + + default: + if (col >= width || !literal && ch < ' ') { + col++; + break; + } + cp = &buf[0][col]; + for (i = 0; i < MAXREP; i++) { + if (i > maxrep) + maxrep = i; + if (*cp == ' ') { + *cp = ch; + if (col > maxcol[i]) + maxcol[i] = col; + break; + } + cp += MAXWIDTH; + } + col++; + break; + } + } + + /* print out lines */ + for (i = 0; i <= maxrep; i++) { + for (cp = buf[i], limit = cp+maxcol[i]; cp <= limit;) { + putc(*cp, o); + *cp++ = ' '; + } + if (i < maxrep) + putc('\r', o); + else + putc(ch, o); + if (++lineno >= length) { + fflush(o); + npages++; + lineno = 0; + } + maxcol[i] = -1; + } + } + if (lineno) { /* be sure to end on a page boundary */ + putchar('\f'); + npages++; + } + if (name && acctfile && access(acctfile, 02) >= 0 && + freopen(acctfile, "a", stdout) != NULL) { + printf("%7.2f\t%s:%s\n", (float)npages, host, name); + } + exit(0); +} diff --git a/usr.sbin/lpr/lpc/Makefile b/usr.sbin/lpr/lpc/Makefile new file mode 100644 index 0000000..10a3d69 --- /dev/null +++ b/usr.sbin/lpr/lpc/Makefile @@ -0,0 +1,12 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= lpc +CFLAGS+=-I${.CURDIR}/../common_source +MAN8= lpc.0 +SRCS= lpc.c cmds.c cmdtab.c startdaemon.c common.c +BINGRP= daemon +BINMODE=2555 +.PATH: ${.CURDIR}/../common_source + +.include "../../Makefile.inc" +.include diff --git a/usr.sbin/lpr/lpc/cmds.c b/usr.sbin/lpr/lpc/cmds.c new file mode 100644 index 0000000..7c2b6fe --- /dev/null +++ b/usr.sbin/lpr/lpc/cmds.c @@ -0,0 +1,1107 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)cmds.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * lpc -- line printer control program -- commands: + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "lp.local.h" +#include "lpc.h" +#include "extern.h" +#include "pathnames.h" + +static void abortpr __P((int)); +static void cleanpr __P((void)); +static void disablepr __P((void)); +static int doarg __P((char *)); +static int doselect __P((struct dirent *)); +static void enablepr __P((void)); +static void prstat __P((void)); +static void putmsg __P((int, char **)); +static int sortq __P((const void *, const void *)); +static void startpr __P((int)); +static void stoppr __P((void)); +static int touch __P((struct queue *)); +static void unlinkf __P((char *)); +static void upstat __P((char *)); + +/* + * kill an existing daemon and disable printing. + */ +void +doabort(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: abort {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + abortpr(1); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + abortpr(1); + } +} + +static void +abortpr(dis) + int dis; +{ + register FILE *fp; + struct stat stbuf; + int pid, fd; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + (void) sprintf(line, "%s/%s", SD, LO); + printf("%s:\n", printer); + + /* + * Turn on the owner execute bit of the lock file to disable printing. + */ + if (dis) { + if (stat(line, &stbuf) >= 0) { + if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) + printf("\tcannot disable printing\n"); + else { + upstat("printing disabled\n"); + printf("\tprinting disabled\n"); + } + } else if (errno == ENOENT) { + if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) + printf("\tcannot create lock file\n"); + else { + (void) close(fd); + upstat("printing disabled\n"); + printf("\tprinting disabled\n"); + printf("\tno daemon to abort\n"); + } + return; + } else { + printf("\tcannot stat lock file\n"); + return; + } + } + /* + * Kill the current daemon to stop printing now. + */ + if ((fp = fopen(line, "r")) == NULL) { + printf("\tcannot open lock file\n"); + return; + } + if (!getline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { + (void) fclose(fp); /* unlocks as well */ + printf("\tno daemon to abort\n"); + return; + } + (void) fclose(fp); + if (kill(pid = atoi(line), SIGTERM) < 0) + printf("\tWarning: daemon (pid %d) not killed\n", pid); + else + printf("\tdaemon (pid %d) killed\n", pid); +} + +/* + * Write a message into the status file. + */ +static void +upstat(msg) + char *msg; +{ + register int fd; + char statfile[BUFSIZ]; + + if (cgetstr(bp, "st", &ST) == -1) + ST = DEFSTAT; + (void) sprintf(statfile, "%s/%s", SD, ST); + umask(0); + fd = open(statfile, O_WRONLY|O_CREAT, 0664); + if (fd < 0 || flock(fd, LOCK_EX) < 0) { + printf("\tcannot create status file\n"); + return; + } + (void) ftruncate(fd, 0); + if (msg == (char *)NULL) + (void) write(fd, "\n", 1); + else + (void) write(fd, msg, strlen(msg)); + (void) close(fd); +} + +/* + * Remove all spool files and temporaries from the spooling area. + */ +void +clean(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: clean {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + cleanpr(); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + cleanpr(); + } +} + +static int +doselect(d) + struct dirent *d; +{ + int c = d->d_name[0]; + + if ((c == 't' || c == 'c' || c == 'd') && d->d_name[1] == 'f') + return(1); + return(0); +} + +/* + * Comparison routine for scandir. Sort by job number and machine, then + * by `cf', `tf', or `df', then by the sequence letter A-Z, a-z. + */ +static int +sortq(a, b) + const void *a, *b; +{ + struct dirent **d1, **d2; + int c1, c2; + + d1 = (struct dirent **)a; + d2 = (struct dirent **)b; + if (c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)) + return(c1); + c1 = (*d1)->d_name[0]; + c2 = (*d2)->d_name[0]; + if (c1 == c2) + return((*d1)->d_name[2] - (*d2)->d_name[2]); + if (c1 == 'c') + return(-1); + if (c1 == 'd' || c2 == 'c') + return(1); + return(-1); +} + +/* + * Remove incomplete jobs from spooling area. + */ +static void +cleanpr() +{ + register int i, n; + register char *cp, *cp1, *lp; + struct dirent **queue; + int nitems; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + printf("%s:\n", printer); + + for (lp = line, cp = SD; *lp++ = *cp++; ) + ; + lp[-1] = '/'; + + nitems = scandir(SD, &queue, doselect, sortq); + if (nitems < 0) { + printf("\tcannot examine spool directory\n"); + return; + } + if (nitems == 0) + return; + i = 0; + do { + cp = queue[i]->d_name; + if (*cp == 'c') { + n = 0; + while (i + 1 < nitems) { + cp1 = queue[i + 1]->d_name; + if (*cp1 != 'd' || strcmp(cp + 3, cp1 + 3)) + break; + i++; + n++; + } + if (n == 0) { + strcpy(lp, cp); + unlinkf(line); + } + } else { + /* + * Must be a df with no cf (otherwise, it would have + * been skipped above) or a tf file (which can always + * be removed). + */ + strcpy(lp, cp); + unlinkf(line); + } + } while (++i < nitems); +} + +static void +unlinkf(name) + char *name; +{ + if (unlink(name) < 0) + printf("\tcannot remove %s\n", name); + else + printf("\tremoved %s\n", name); +} + +/* + * Enable queuing to the printer (allow lpr's). + */ +void +enable(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: enable {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + enablepr(); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + enablepr(); + } +} + +static void +enablepr() +{ + struct stat stbuf; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + (void) sprintf(line, "%s/%s", SD, LO); + printf("%s:\n", printer); + + /* + * Turn off the group execute bit of the lock file to enable queuing. + */ + if (stat(line, &stbuf) >= 0) { + if (chmod(line, stbuf.st_mode & 0767) < 0) + printf("\tcannot enable queuing\n"); + else + printf("\tqueuing enabled\n"); + } +} + +/* + * Disable queuing. + */ +void +disable(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: disable {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + disablepr(); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + disablepr(); + } +} + +static void +disablepr() +{ + register int fd; + struct stat stbuf; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + (void) sprintf(line, "%s/%s", SD, LO); + printf("%s:\n", printer); + /* + * Turn on the group execute bit of the lock file to disable queuing. + */ + if (stat(line, &stbuf) >= 0) { + if (chmod(line, (stbuf.st_mode & 0777) | 010) < 0) + printf("\tcannot disable queuing\n"); + else + printf("\tqueuing disabled\n"); + } else if (errno == ENOENT) { + if ((fd = open(line, O_WRONLY|O_CREAT, 0670)) < 0) + printf("\tcannot create lock file\n"); + else { + (void) close(fd); + printf("\tqueuing disabled\n"); + } + return; + } else + printf("\tcannot stat lock file\n"); +} + +/* + * Disable queuing and printing and put a message into the status file + * (reason for being down). + */ +void +down(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: down {all | printer} [message ...]\n"); + return; + } + if (!strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + putmsg(argc - 2, argv + 2); + } + return; + } + printer = argv[1]; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + return; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + return; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + putmsg(argc - 2, argv + 2); +} + +static void +putmsg(argc, argv) + int argc; + char **argv; +{ + register int fd; + register char *cp1, *cp2; + char buf[1024]; + struct stat stbuf; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + if (cgetstr(bp, "st", &ST) == -1) + ST = DEFSTAT; + printf("%s:\n", printer); + /* + * Turn on the group execute bit of the lock file to disable queuing and + * turn on the owner execute bit of the lock file to disable printing. + */ + (void) sprintf(line, "%s/%s", SD, LO); + if (stat(line, &stbuf) >= 0) { + if (chmod(line, (stbuf.st_mode & 0777) | 0110) < 0) + printf("\tcannot disable queuing\n"); + else + printf("\tprinter and queuing disabled\n"); + } else if (errno == ENOENT) { + if ((fd = open(line, O_WRONLY|O_CREAT, 0770)) < 0) + printf("\tcannot create lock file\n"); + else { + (void) close(fd); + printf("\tprinter and queuing disabled\n"); + } + return; + } else + printf("\tcannot stat lock file\n"); + /* + * Write the message into the status file. + */ + (void) sprintf(line, "%s/%s", SD, ST); + fd = open(line, O_WRONLY|O_CREAT, 0664); + if (fd < 0 || flock(fd, LOCK_EX) < 0) { + printf("\tcannot create status file\n"); + return; + } + (void) ftruncate(fd, 0); + if (argc <= 0) { + (void) write(fd, "\n", 1); + (void) close(fd); + return; + } + cp1 = buf; + while (--argc >= 0) { + cp2 = *argv++; + while (*cp1++ = *cp2++) + ; + cp1[-1] = ' '; + } + cp1[-1] = '\n'; + *cp1 = '\0'; + (void) write(fd, buf, strlen(buf)); + (void) close(fd); +} + +/* + * Exit lpc + */ +void +quit(argc, argv) + int argc; + char *argv[]; +{ + exit(0); +} + +/* + * Kill and restart the daemon. + */ +void +restart(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: restart {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + abortpr(0); + startpr(0); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + abortpr(0); + startpr(0); + } +} + +/* + * Enable printing on the specified printer and startup the daemon. + */ +void +startcmd(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: start {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + startpr(1); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + startpr(1); + } +} + +static void +startpr(enable) + int enable; +{ + struct stat stbuf; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + (void) sprintf(line, "%s/%s", SD, LO); + printf("%s:\n", printer); + + /* + * Turn off the owner execute bit of the lock file to enable printing. + */ + if (enable && stat(line, &stbuf) >= 0) { + if (chmod(line, stbuf.st_mode & (enable==2 ? 0666 : 0677)) < 0) + printf("\tcannot enable printing\n"); + else + printf("\tprinting enabled\n"); + } + if (!startdaemon(printer)) + printf("\tcouldn't start daemon\n"); + else + printf("\tdaemon started\n"); +} + +/* + * Print the status of each queue listed or all the queues. + */ +void +status(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + prstat(); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + prstat(); + } +} + +/* + * Print the status of the printer queue. + */ +static void +prstat() +{ + struct stat stbuf; + register int fd, i; + register struct dirent *dp; + DIR *dirp; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + if (cgetstr(bp, "st", &ST) == -1) + ST = DEFSTAT; + printf("%s:\n", printer); + (void) sprintf(line, "%s/%s", SD, LO); + if (stat(line, &stbuf) >= 0) { + printf("\tqueuing is %s\n", + (stbuf.st_mode & 010) ? "disabled" : "enabled"); + printf("\tprinting is %s\n", + (stbuf.st_mode & 0100) ? "disabled" : "enabled"); + } else { + printf("\tqueuing is enabled\n"); + printf("\tprinting is enabled\n"); + } + if ((dirp = opendir(SD)) == NULL) { + printf("\tcannot examine spool directory\n"); + return; + } + i = 0; + while ((dp = readdir(dirp)) != NULL) { + if (*dp->d_name == 'c' && dp->d_name[1] == 'f') + i++; + } + closedir(dirp); + if (i == 0) + printf("\tno entries\n"); + else if (i == 1) + printf("\t1 entry in spool area\n"); + else + printf("\t%d entries in spool area\n", i); + fd = open(line, O_RDONLY); + if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { + (void) close(fd); /* unlocks as well */ + printf("\tno daemon present\n"); + return; + } + (void) close(fd); + putchar('\t'); + (void) sprintf(line, "%s/%s", SD, ST); + fd = open(line, O_RDONLY); + if (fd >= 0) { + (void) flock(fd, LOCK_SH); + while ((i = read(fd, line, sizeof(line))) > 0) + (void) fwrite(line, 1, i, stdout); + (void) close(fd); /* unlocks as well */ + } +} + +/* + * Stop the specified daemon after completing the current job and disable + * printing. + */ +void +stop(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: stop {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + stoppr(); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + stoppr(); + } +} + +static void +stoppr() +{ + register int fd; + struct stat stbuf; + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + (void) sprintf(line, "%s/%s", SD, LO); + printf("%s:\n", printer); + + /* + * Turn on the owner execute bit of the lock file to disable printing. + */ + if (stat(line, &stbuf) >= 0) { + if (chmod(line, (stbuf.st_mode & 0777) | 0100) < 0) + printf("\tcannot disable printing\n"); + else { + upstat("printing disabled\n"); + printf("\tprinting disabled\n"); + } + } else if (errno == ENOENT) { + if ((fd = open(line, O_WRONLY|O_CREAT, 0760)) < 0) + printf("\tcannot create lock file\n"); + else { + (void) close(fd); + upstat("printing disabled\n"); + printf("\tprinting disabled\n"); + } + } else + printf("\tcannot stat lock file\n"); +} + +struct queue **queue; +int nitems; +time_t mtime; + +/* + * Put the specified jobs at the top of printer queue. + */ +void +topq(argc, argv) + int argc; + char *argv[]; +{ + register int i; + struct stat stbuf; + int status, changed; + + if (argc < 3) { + printf("Usage: topq printer [jobnum ...] [user ...]\n"); + return; + } + + --argc; + printer = *++argv; + status = cgetent(&bp, printcapdb, printer); + if (status == -2) { + printf("cannot open printer description file\n"); + return; + } else if (status == -1) { + printf("%s: unknown printer\n", printer); + return; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + printf("%s:\n", printer); + + if (chdir(SD) < 0) { + printf("\tcannot chdir to %s\n", SD); + return; + } + nitems = getq(&queue); + if (nitems == 0) + return; + changed = 0; + mtime = queue[0]->q_time; + for (i = argc; --i; ) { + if (doarg(argv[i]) == 0) { + printf("\tjob %s is not in the queue\n", argv[i]); + continue; + } else + changed++; + } + for (i = 0; i < nitems; i++) + free(queue[i]); + free(queue); + if (!changed) { + printf("\tqueue order unchanged\n"); + return; + } + /* + * Turn on the public execute bit of the lock file to + * get lpd to rebuild the queue after the current job. + */ + if (changed && stat(LO, &stbuf) >= 0) + (void) chmod(LO, (stbuf.st_mode & 0777) | 01); +} + +/* + * Reposition the job by changing the modification time of + * the control file. + */ +static int +touch(q) + struct queue *q; +{ + struct timeval tvp[2]; + + tvp[0].tv_sec = tvp[1].tv_sec = --mtime; + tvp[0].tv_usec = tvp[1].tv_usec = 0; + return(utimes(q->q_name, tvp)); +} + +/* + * Checks if specified job name is in the printer's queue. + * Returns: negative (-1) if argument name is not in the queue. + */ +static int +doarg(job) + char *job; +{ + register struct queue **qq; + register int jobnum, n; + register char *cp, *machine; + int cnt = 0; + FILE *fp; + + /* + * Look for a job item consisting of system name, colon, number + * (example: ucbarpa:114) + */ + if ((cp = index(job, ':')) != NULL) { + machine = job; + *cp++ = '\0'; + job = cp; + } else + machine = NULL; + + /* + * Check for job specified by number (example: 112 or 235ucbarpa). + */ + if (isdigit(*job)) { + jobnum = 0; + do + jobnum = jobnum * 10 + (*job++ - '0'); + while (isdigit(*job)); + for (qq = queue + nitems; --qq >= queue; ) { + n = 0; + for (cp = (*qq)->q_name+3; isdigit(*cp); ) + n = n * 10 + (*cp++ - '0'); + if (jobnum != n) + continue; + if (*job && strcmp(job, cp) != 0) + continue; + if (machine != NULL && strcmp(machine, cp) != 0) + continue; + if (touch(*qq) == 0) { + printf("\tmoved %s\n", (*qq)->q_name); + cnt++; + } + } + return(cnt); + } + /* + * Process item consisting of owner's name (example: henry). + */ + for (qq = queue + nitems; --qq >= queue; ) { + if ((fp = fopen((*qq)->q_name, "r")) == NULL) + continue; + while (getline(fp) > 0) + if (line[0] == 'P') + break; + (void) fclose(fp); + if (line[0] != 'P' || strcmp(job, line+1) != 0) + continue; + if (touch(*qq) == 0) { + printf("\tmoved %s\n", (*qq)->q_name); + cnt++; + } + } + return(cnt); +} + +/* + * Enable everything and start printer (undo `down'). + */ +void +up(argc, argv) + int argc; + char *argv[]; +{ + register int c, status; + register char *cp1, *cp2; + char prbuf[100]; + + if (argc == 1) { + printf("Usage: up {all | printer ...}\n"); + return; + } + if (argc == 2 && !strcmp(argv[1], "all")) { + printer = prbuf; + while (cgetnext(&bp, printcapdb) > 0) { + cp1 = prbuf; + cp2 = bp; + while ((c = *cp2++) && c != '|' && c != ':') + *cp1++ = c; + *cp1 = '\0'; + startpr(2); + } + return; + } + while (--argc) { + printer = *++argv; + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + printf("cannot open printer description file\n"); + continue; + } else if (status == -1) { + printf("unknown printer %s\n", printer); + continue; + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + startpr(2); + } +} diff --git a/usr.sbin/lpr/lpc/cmdtab.c b/usr.sbin/lpr/lpc/cmdtab.c new file mode 100644 index 0000000..7619791 --- /dev/null +++ b/usr.sbin/lpr/lpc/cmdtab.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include + +#include "lpc.h" +#include "extern.h" + +/* + * lpc -- command tables + */ +char aborthelp[] = "terminate a spooling daemon immediately and disable printing"; +char cleanhelp[] = "remove cruft files from a queue"; +char enablehelp[] = "turn a spooling queue on"; +char disablehelp[] = "turn a spooling queue off"; +char downhelp[] = "do a 'stop' followed by 'disable' and put a message in status"; +char helphelp[] = "get help on commands"; +char quithelp[] = "exit lpc"; +char restarthelp[] = "kill (if possible) and restart a spooling daemon"; +char starthelp[] = "enable printing and start a spooling daemon"; +char statushelp[] = "show status of daemon and queue"; +char stophelp[] = "stop a spooling daemon after current job completes and disable printing"; +char topqhelp[] = "put job at top of printer queue"; +char uphelp[] = "enable everything and restart spooling daemon"; + +struct cmd cmdtab[] = { + { "abort", aborthelp, doabort, 1 }, + { "clean", cleanhelp, clean, 1 }, + { "enable", enablehelp, enable, 1 }, + { "exit", quithelp, quit, 0 }, + { "disable", disablehelp, disable, 1 }, + { "down", downhelp, down, 1 }, + { "help", helphelp, help, 0 }, + { "quit", quithelp, quit, 0 }, + { "restart", restarthelp, restart, 0 }, + { "start", starthelp, startcmd, 1 }, + { "status", statushelp, status, 0 }, + { "stop", stophelp, stop, 1 }, + { "topq", topqhelp, topq, 1 }, + { "up", uphelp, up, 1 }, + { "?", helphelp, help, 0 }, + { 0 }, +}; + +int NCMDS = sizeof (cmdtab) / sizeof (cmdtab[0]); diff --git a/usr.sbin/lpr/lpc/extern.h b/usr.sbin/lpr/lpc/extern.h new file mode 100644 index 0000000..1b807b1 --- /dev/null +++ b/usr.sbin/lpr/lpc/extern.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 6/6/93 + */ + + +#include + + +__BEGIN_DECLS +void clean __P((int, char **)); +void disable __P((int, char **)); +void doabort __P((int, char **)); +void down __P((int, char **)); +void enable __P((int, char **)); +void help __P((int, char **)); +void quit __P((int, char **)); +void restart __P((int, char **)); +void startcmd __P((int, char **)); +void status __P((int, char **)); +void stop __P((int, char **)); +void topq __P((int, char **)); +void up __P((int, char **)); +__END_DECLS + +extern int NCMDS; +extern struct cmd cmdtab[]; diff --git a/usr.sbin/lpr/lpc/lpc.8 b/usr.sbin/lpr/lpc/lpc.8 new file mode 100644 index 0000000..a786adc --- /dev/null +++ b/usr.sbin/lpr/lpc/lpc.8 @@ -0,0 +1,174 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)lpc.8 8.3 (Berkeley) 4/19/94 +.\" +.Dd April 19, 1994 +.Dt LPC 8 +.Os BSD 4.2 +.Sh NAME +.Nm lpc +.Nd line printer control program +.Sh SYNOPSIS +.Nm lpc +.Oo +.Ar command +.Op Ar argument ... +.Oc +.Sh DESCRIPTION +.Nm Lpc +is used by the system administrator to control the +operation of the line printer system. +For each line printer configured in +.Pa /etc/printcap , +.Nm lpc +may be used to: +.Bl -bullet -offset indent +.It +disable or enable a printer, +.It +disable or enable a printer's spooling queue, +.It +rearrange the order of jobs in a spooling queue, +.It +find the status of printers, and their associated +spooling queues and printer daemons. +.El +.Pp +Without any arguments, +.Nm lpc +will prompt for commands from the standard input. +If arguments are supplied, +.Nm lpc +interprets the first argument as a command and the remaining +arguments as parameters to the command. The standard input +may be redirected causing +.Nm lpc +to read commands from file. +Commands may be abbreviated; +the following is the list of recognized commands. +.Pp +.Bl -tag -width Ds -compact +.It Ic \&? No [ command ... ] +.It Ic help No [ command ... ] +Print a short description of each command specified in the argument list, +or, if no argument is given, a list of the recognized commands. +.Pp +.It Ic abort No {\ all\ |\ printer\ } +Terminate an active spooling daemon on the local host immediately and +then disable printing (preventing new daemons from being started by +.Xr lpr ) +for the specified printers. +.Pp +.It Ic clean No {\ all\ |\ printer\ } +Remove any temporary files, data files, and control files that cannot +be printed (i.e., do not form a complete printer job) +from the specified printer queue(s) on the local machine. +.Pp +.It Ic disable No {\ all\ |\ printer\ } +Turn the specified printer queues off. This prevents new +printer jobs from being entered into the queue by +.Xr lpr . +.Pp +.It Ic down No {\ all\ |\ printer\ } message ... +Turn the specified printer queue off, disable printing and put +.Em message +in the printer status file. The message doesn't need to be quoted, the +remaining arguments are treated like +.Xr echo 1 . +This is normally used to take a printer down and let others know why +.Xr lpq 1 +will indicate the printer is down and print the status message). +.Pp +.It Ic enable No {\ all\ |\ printer\ } +Enable spooling on the local queue for the listed printers. +This will allow +.Xr lpr 1 +to put new jobs in the spool queue. +.Pp +.It Ic exit +.It Ic quit +Exit from lpc. +.Pp +.It Ic restart No {\ all\ |\ printer\ } +Attempt to start a new printer daemon. +This is useful when some abnormal condition causes the daemon to +die unexpectedly, leaving jobs in the queue. +.Xr Lpq +will report that there is no daemon present when this condition occurs. +If the user is the super-user, +try to abort the current daemon first (i.e., kill and restart a stuck daemon). +.Pp +.It Ic start No {\ all\ |\ printer\ } +Enable printing and start a spooling daemon for the listed printers. +.Pp +.It Ic status No {\ all\ |\ printer\ } +Display the status of daemons and queues on the local machine. +.Pp +.It Ic stop No {\ all\ |\ printer\ } +Stop a spooling daemon after the current job completes and disable +printing. +.Pp +.It Ic topq No printer\ [\ jobnum\ ...\ ]\ [\ user\ ...\ ] +Place the jobs in the order listed at the top of the printer queue. +.Pp +.It Ic up No {\ all\ |\ printer\ } +Enable everything and start a new printer daemon. Undoes the effects of +.Ic down . +.Sh FILES +.Bl -tag -width /var/spool/*/lockx -compact +.It Pa /etc/printcap +printer description file +.It Pa /var/spool/* +spool directories +.It Pa /var/spool/*/lock +lock file for queue control +.El +.Sh SEE ALSO +.Xr lpd 8 , +.Xr lpr 1 , +.Xr lpq 1 , +.Xr lprm 1 , +.Xr printcap 5 +.Sh DIAGNOSTICS +.Bl -tag -width Ds +.It Sy "?Ambiguous command" +abbreviation matches more than one command +.It Sy "?Invalid command" +no match was found +.It Sy "?Privileged command" +command can be executed by root only +.El +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/usr.sbin/lpr/lpc/lpc.c b/usr.sbin/lpr/lpc/lpc.c new file mode 100644 index 0000000..01cfc12 --- /dev/null +++ b/usr.sbin/lpr/lpc/lpc.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)lpc.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "lpc.h" +#include "extern.h" + +/* + * lpc -- line printer control program + */ + +int fromatty; + +char cmdline[200]; +int margc; +char *margv[20]; +int top; + +jmp_buf toplevel; + +static void cmdscanner __P((int)); +static struct cmd *getcmd __P((char *)); +static void intr __P((int)); +static void makeargv __P((void)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + register struct cmd *c; + + name = argv[0]; + openlog("lpd", 0, LOG_LPR); + + if (--argc > 0) { + c = getcmd(*++argv); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + exit(1); + } + if (c == 0) { + printf("?Invalid command\n"); + exit(1); + } + if (c->c_priv && getuid()) { + printf("?Privileged command\n"); + exit(1); + } + (*c->c_handler)(argc, argv); + exit(0); + } + fromatty = isatty(fileno(stdin)); + top = setjmp(toplevel) == 0; + if (top) + signal(SIGINT, intr); + for (;;) { + cmdscanner(top); + top = 1; + } +} + +static void +intr(signo) + int signo; +{ + if (!fromatty) + exit(0); + longjmp(toplevel, 1); +} + +/* + * Command parser. + */ +static void +cmdscanner(top) + int top; +{ + register struct cmd *c; + + if (!top) + putchar('\n'); + for (;;) { + if (fromatty) { + printf("lpc> "); + fflush(stdout); + } + if (fgets(cmdline, sizeof(cmdline), stdin) == 0) + quit(0, NULL); + if (cmdline[0] == 0 || cmdline[0] == '\n') + break; + makeargv(); + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + continue; + } + if (c == 0) { + printf("?Invalid command\n"); + continue; + } + if (c->c_priv && getuid()) { + printf("?Privileged command\n"); + continue; + } + (*c->c_handler)(margc, margv); + } + longjmp(toplevel, 0); +} + +struct cmd * +getcmd(name) + register char *name; +{ + register char *p, *q; + register struct cmd *c, *found; + register int nmatches, longest; + + longest = 0; + nmatches = 0; + found = 0; + for (c = cmdtab; p = c->c_name; c++) { + for (q = name; *q == *p++; q++) + if (*q == 0) /* exact match? */ + return(c); + if (!*q) { /* the name was a prefix */ + if (q - name > longest) { + longest = q - name; + nmatches = 1; + found = c; + } else if (q - name == longest) + nmatches++; + } + } + if (nmatches > 1) + return((struct cmd *)-1); + return(found); +} + +/* + * Slice a string up into argc/argv. + */ +static void +makeargv() +{ + register char *cp; + register char **argp = margv; + + margc = 0; + for (cp = cmdline; *cp;) { + while (isspace(*cp)) + cp++; + if (*cp == '\0') + break; + *argp++ = cp; + margc += 1; + while (*cp != '\0' && !isspace(*cp)) + cp++; + if (*cp == '\0') + break; + *cp++ = '\0'; + } + *argp++ = 0; +} + +#define HELPINDENT (sizeof ("directory")) + +/* + * Help command. + */ +void +help(argc, argv) + int argc; + char *argv[]; +{ + register struct cmd *c; + + if (argc == 1) { + register int i, j, w; + int columns, width = 0, lines; + extern int NCMDS; + + printf("Commands may be abbreviated. Commands are:\n\n"); + for (c = cmdtab; c->c_name; c++) { + int len = strlen(c->c_name); + + if (len > width) + width = len; + } + width = (width + 8) &~ 7; + columns = 80 / width; + if (columns == 0) + columns = 1; + lines = (NCMDS + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + c = cmdtab + j * lines + i; + if (c->c_name) + printf("%s", c->c_name); + if (c + lines >= &cmdtab[NCMDS]) { + printf("\n"); + break; + } + w = strlen(c->c_name); + while (w < width) { + w = (w + 8) &~ 7; + putchar('\t'); + } + } + } + return; + } + while (--argc > 0) { + register char *arg; + arg = *++argv; + c = getcmd(arg); + if (c == (struct cmd *)-1) + printf("?Ambiguous help command %s\n", arg); + else if (c == (struct cmd *)0) + printf("?Invalid help command %s\n", arg); + else + printf("%-*s\t%s\n", HELPINDENT, + c->c_name, c->c_help); + } +} diff --git a/usr.sbin/lpr/lpc/lpc.h b/usr.sbin/lpr/lpc/lpc.h new file mode 100644 index 0000000..5e71203 --- /dev/null +++ b/usr.sbin/lpr/lpc/lpc.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)lpc.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Line printer control program. + */ +struct cmd { + char *c_name; /* command name */ + char *c_help; /* help message */ + /* routine to do the work */ + void (*c_handler) __P((int, char *[])); + int c_priv; /* privileged command */ +}; diff --git a/usr.sbin/lpr/lpd/Makefile b/usr.sbin/lpr/lpd/Makefile new file mode 100644 index 0000000..da95bac --- /dev/null +++ b/usr.sbin/lpr/lpd/Makefile @@ -0,0 +1,11 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= lpd +CFLAGS+=-I${.CURDIR}/../common_source +MAN8= lpd.0 +SRCS= lpd.c printjob.c recvjob.c displayq.c rmjob.c startdaemon.c \ + lpdchar.c common.c +.PATH: ${.CURDIR}/../common_source + +.include "../../Makefile.inc" +.include diff --git a/usr.sbin/lpr/lpd/extern.h b/usr.sbin/lpr/lpd/extern.h new file mode 100644 index 0000000..64dec12 --- /dev/null +++ b/usr.sbin/lpr/lpd/extern.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 6/6/93 + */ + +#include + +void printjob __P((void)); +void recvjob __P((void)); diff --git a/usr.sbin/lpr/lpd/lpd.8 b/usr.sbin/lpr/lpd/lpd.8 new file mode 100644 index 0000000..1e4677f --- /dev/null +++ b/usr.sbin/lpr/lpd/lpd.8 @@ -0,0 +1,249 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)lpd.8 8.3 (Berkeley) 4/19/94 +.\" +.Dd April 19, 1994 +.Dt LPD 8 +.Os BSD 4.2 +.Sh NAME +.Nm lpd +.Nd line printer spooler daemon +.Sh SYNOPSIS +.Nm lpd +.Op Fl l +.Op Ar port# +.Sh DESCRIPTION +.Nm Lpd +is the line printer daemon (spool area handler) and is normally invoked +at boot time from the +.Xr rc 8 +file. It makes a single pass through the +.Xr printcap 5 +file to find out about the existing printers and +prints any files left after a crash. It then uses the system calls +.Xr listen 2 +and +.Xr accept 2 +to receive requests to print files in the queue, +transfer files to the spooling area, display the queue, +or remove jobs from the queue. In each case, it forks a child to handle +the request so the parent can continue to listen for more requests. +.Pp +Available options: +.Bl -tag -width Ds +.It Fl l +The +.Fl l +flag causes +.Nm lpd +to log valid requests received from the network. This can be useful +for debugging purposes. +.It Ar "port#" +The Internet port number used to rendezvous +with other processes is normally obtained with +.Xr getservbyname 3 +but can be changed with the +.Ar port# +argument. +.El +.Pp +Access control is provided by two means. First, all requests must come from +one of the machines listed in the file +.Pa /etc/hosts.equiv +or +.Pa /etc/hosts.lpd . +Second, if the +.Li rs +capability is specified in the +.Xr printcap +entry for the printer being accessed, +.Em lpr +requests will only be honored for those users with accounts on the +machine with the printer. +.Pp +The file +.Em minfree +in each spool directory contains the number of disk blocks to leave free +so that the line printer queue won't completely fill the disk. +The +.Em minfree +file can be edited with your favorite text editor. +.Pp +The daemon begins processing files +after it has successfully set the lock for exclusive +access (described a bit later), +and scans the spool directory +for files beginning with +.Em cf . +Lines in each +.Em cf +file specify files to be printed or non-printing actions to be +performed. Each such line begins with a key character +to specify what to do with the remainder of the line. +.Bl -tag -width Ds +.It J +Job Name. String to be used for the job name on the burst page. +.It C +Classification. String to be used for the classification line +on the burst page. +.It L +Literal. The line contains identification info from +the password file and causes the banner page to be printed. +.It T +Title. String to be used as the title for +.Xr pr 1 . +.It H +Host Name. Name of the machine where +.Xr lpr +was invoked. +.It P +Person. Login name of the person who invoked +.Xr lpr . +This is used to verify ownership by +.Xr lprm . +.It M +Send mail to the specified user when the current print job completes. +.It f +Formatted File. Name of a file to print which is already formatted. +.It l +Like ``f'' but passes control characters and does not make page breaks. +.It p +Name of a file to print using +.Xr pr 1 +as a filter. +.It t +Troff File. The file contains +.Xr troff 1 +output (cat phototypesetter commands). +.It n +Ditroff File. The file contains device independent troff +output. +.It r +DVI File. The file contains +.Tn Tex l +output +DVI format from Standford. +.It g +Graph File. The file contains data produced by +.Xr plot 3 . +.It c +Cifplot File. The file contains data produced by +.Em cifplot . +.It v +The file contains a raster image. +.It r +The file contains text data with +FORTRAN carriage control characters. +.It \&1 +Troff Font R. Name of the font file to use instead of the default. +.It \&2 +Troff Font I. Name of the font file to use instead of the default. +.It \&3 +Troff Font B. Name of the font file to use instead of the default. +.It \&4 +Troff Font S. Name of the font file to use instead of the default. +.It W +Width. Changes the page width (in characters) used by +.Xr pr 1 +and the text filters. +.It I +Indent. The number of characters to indent the output by (in ascii). +.It U +Unlink. Name of file to remove upon completion of printing. +.It N +File name. The name of the file which is being printed, or a blank +for the standard input (when +.Xr lpr +is invoked in a pipeline). +.El +.Pp +If a file cannot be opened, a message will be logged via +.Xr syslog 3 +using the +.Em LOG_LPR +facility. +.Nm Lpd +will try up to 20 times +to reopen a file it expects to be there, after which it will +skip the file to be printed. +.Pp +.Nm Lpd +uses +.Xr flock 2 +to provide exclusive access to the lock file and to prevent multiple +daemons from becoming active simultaneously. If the daemon should be killed +or die unexpectedly, the lock file need not be removed. +The lock file is kept in a readable +.Tn ASCII +form +and contains two lines. +The first is the process id of the daemon and the second is the control +file name of the current job being printed. The second line is updated to +reflect the current status of +.Nm lpd +for the programs +.Xr lpq 1 +and +.Xr lprm 1 . +.Sh FILES +.Bl -tag -width "/var/spool/*/minfree" -compact +.It Pa /etc/printcap +printer description file +.It Pa /var/spool/* +spool directories +.It Pa /var/spool/*/minfree +minimum free space to leave +.It Pa /dev/lp* +line printer devices +.It Pa /dev/printer +socket for local requests +.It Pa /etc/hosts.equiv +lists machine names allowed printer access +.It Pa /etc/hosts.lpd +lists machine names allowed printer access, +but not under same administrative control. +.El +.Sh SEE ALSO +.Xr lpc 8 , +.Xr pac 1 , +.Xr lpr 1 , +.Xr lpq 1 , +.Xr lprm 1 , +.Xr syslog 3 , +.Xr printcap 5 +.Rs +.%T "4.2 BSD Line Printer Spooler Manual" +.Re +.Sh HISTORY +An +.Nm +daemon appeared in Version 6 AT&T UNIX. diff --git a/usr.sbin/lpr/lpd/lpd.c b/usr.sbin/lpr/lpd/lpd.c new file mode 100644 index 0000000..aaf72b7 --- /dev/null +++ b/usr.sbin/lpr/lpd/lpd.c @@ -0,0 +1,507 @@ +/* + * Copyright (c) 1983, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)lpd.c 8.4 (Berkeley) 4/17/94"; +#endif /* not lint */ + +/* + * lpd -- line printer daemon. + * + * Listen for a connection and perform the requested operation. + * Operations are: + * \1printer\n + * check the queue for jobs and print any found. + * \2printer\n + * receive a job from another machine and queue it. + * \3printer [users ...] [jobs ...]\n + * return the current state of the queue (short form). + * \4printer [users ...] [jobs ...]\n + * return the current state of the queue (long form). + * \5printer person [users ...] [jobs ...]\n + * remove jobs from the queue. + * + * Strategy to maintain protected spooling area: + * 1. Spooling area is writable only by daemon and spooling group + * 2. lpr runs setuid root and setgrp spooling group; it uses + * root to access any file it wants (verifying things before + * with an access call) and group id to know how it should + * set up ownership of files in the spooling area. + * 3. Files in spooling area are owned by root, group spooling + * group, with mode 660. + * 4. lpd, lpq and lprm run setuid daemon and setgrp spooling group to + * access files and printer. Users can't get to anything + * w/o help of lpq and lprm programs. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "lp.local.h" +#include "pathnames.h" +#include "extern.h" + +int lflag; /* log requests flag */ +int from_remote; /* from remote socket */ + +static void reapchild __P((int)); +static void mcleanup __P((int)); +static void doit __P((void)); +static void startup __P((void)); +static void chkhost __P((struct sockaddr_in *)); + +int +main(argc, argv) + int argc; + char **argv; +{ + int f, funix, finet, options, fromlen; + fd_set defreadfds; + struct sockaddr_un un, fromunix; + struct sockaddr_in sin, frominet; + int omask, lfd; + + options = 0; + gethostname(host, sizeof(host)); + name = argv[0]; + + while (--argc > 0) { + argv++; + if (argv[0][0] == '-') + switch (argv[0][1]) { + case 'd': + options |= SO_DEBUG; + break; + case 'l': + lflag++; + break; + } + } + +#ifndef DEBUG + /* + * Set up standard environment by detaching from the parent. + */ + daemon(0, 0); +#endif + + openlog("lpd", LOG_PID, LOG_LPR); + syslog(LOG_INFO, "restarted"); + (void) umask(0); + lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT, 0644); + if (lfd < 0) { + syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); + exit(1); + } + if (flock(lfd, LOCK_EX|LOCK_NB) < 0) { + if (errno == EWOULDBLOCK) /* active deamon present */ + exit(0); + syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); + exit(1); + } + ftruncate(lfd, 0); + /* + * write process id for others to know + */ + sprintf(line, "%u\n", getpid()); + f = strlen(line); + if (write(lfd, line, f) != f) { + syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); + exit(1); + } + signal(SIGCHLD, reapchild); + /* + * Restart all the printers. + */ + startup(); + (void) unlink(_PATH_SOCKETNAME); + funix = socket(AF_UNIX, SOCK_STREAM, 0); + if (funix < 0) { + syslog(LOG_ERR, "socket: %m"); + exit(1); + } +#define mask(s) (1 << ((s) - 1)) + omask = sigblock(mask(SIGHUP)|mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM)); + signal(SIGHUP, mcleanup); + signal(SIGINT, mcleanup); + signal(SIGQUIT, mcleanup); + signal(SIGTERM, mcleanup); + memset(&un, 0, sizeof(un)); + un.sun_family = AF_UNIX; + strcpy(un.sun_path, _PATH_SOCKETNAME); +#ifndef SUN_LEN +#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2) +#endif + if (bind(funix, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) { + syslog(LOG_ERR, "ubind: %m"); + exit(1); + } + sigsetmask(omask); + FD_ZERO(&defreadfds); + FD_SET(funix, &defreadfds); + listen(funix, 5); + finet = socket(AF_INET, SOCK_STREAM, 0); + if (finet >= 0) { + struct servent *sp; + + if (options & SO_DEBUG) + if (setsockopt(finet, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) { + syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); + mcleanup(0); + } + sp = getservbyname("printer", "tcp"); + if (sp == NULL) { + syslog(LOG_ERR, "printer/tcp: unknown service"); + mcleanup(0); + } + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = sp->s_port; + if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + syslog(LOG_ERR, "bind: %m"); + mcleanup(0); + } + FD_SET(finet, &defreadfds); + listen(finet, 5); + } + /* + * Main loop: accept, do a request, continue. + */ + memset(&frominet, 0, sizeof(frominet)); + memset(&fromunix, 0, sizeof(fromunix)); + for (;;) { + int domain, nfds, s; + fd_set readfds; + + FD_COPY(&defreadfds, &readfds); + nfds = select(20, &readfds, 0, 0, 0); + if (nfds <= 0) { + if (nfds < 0 && errno != EINTR) + syslog(LOG_WARNING, "select: %m"); + continue; + } + if (FD_ISSET(funix, &readfds)) { + domain = AF_UNIX, fromlen = sizeof(fromunix); + s = accept(funix, + (struct sockaddr *)&fromunix, &fromlen); + } else /* if (FD_ISSET(finet, &readfds)) */ { + domain = AF_INET, fromlen = sizeof(frominet); + s = accept(finet, + (struct sockaddr *)&frominet, &fromlen); + } + if (s < 0) { + if (errno != EINTR) + syslog(LOG_WARNING, "accept: %m"); + continue; + } + if (fork() == 0) { + signal(SIGCHLD, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + (void) close(funix); + (void) close(finet); + dup2(s, 1); + (void) close(s); + if (domain == AF_INET) { + from_remote = 1; + chkhost(&frominet); + } else + from_remote = 0; + doit(); + exit(0); + } + (void) close(s); + } +} + +static void +reapchild(signo) + int signo; +{ + union wait status; + + while (wait3((int *)&status, WNOHANG, 0) > 0) + ; +} + +static void +mcleanup(signo) + int signo; +{ + if (lflag) + syslog(LOG_INFO, "exiting"); + unlink(_PATH_SOCKETNAME); + exit(0); +} + +/* + * Stuff for handling job specifications + */ +char *user[MAXUSERS]; /* users to process */ +int users; /* # of users in user array */ +int requ[MAXREQUESTS]; /* job number of spool entries */ +int requests; /* # of spool requests */ +char *person; /* name of person doing lprm */ + +char fromb[MAXHOSTNAMELEN]; /* buffer for client's machine name */ +char cbuf[BUFSIZ]; /* command line buffer */ +char *cmdnames[] = { + "null", + "printjob", + "recvjob", + "displayq short", + "displayq long", + "rmjob" +}; + +static void +doit() +{ + register char *cp; + register int n; + + for (;;) { + cp = cbuf; + do { + if (cp >= &cbuf[sizeof(cbuf) - 1]) + fatal("Command line too long"); + if ((n = read(1, cp, 1)) != 1) { + if (n < 0) + fatal("Lost connection"); + return; + } + } while (*cp++ != '\n'); + *--cp = '\0'; + cp = cbuf; + if (lflag) { + if (*cp >= '\1' && *cp <= '\5') + syslog(LOG_INFO, "%s requests %s %s", + from, cmdnames[*cp], cp+1); + else + syslog(LOG_INFO, "bad request (%d) from %s", + *cp, from); + } + switch (*cp++) { + case '\1': /* check the queue and print any jobs there */ + printer = cp; + printjob(); + break; + case '\2': /* receive files to be queued */ + if (!from_remote) { + syslog(LOG_INFO, "illegal request (%d)", *cp); + exit(1); + } + printer = cp; + recvjob(); + break; + case '\3': /* display the queue (short form) */ + case '\4': /* display the queue (long form) */ + printer = cp; + while (*cp) { + if (*cp != ' ') { + cp++; + continue; + } + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp == '\0') + break; + if (isdigit(*cp)) { + if (requests >= MAXREQUESTS) + fatal("Too many requests"); + requ[requests++] = atoi(cp); + } else { + if (users >= MAXUSERS) + fatal("Too many users"); + user[users++] = cp; + } + } + displayq(cbuf[0] - '\3'); + exit(0); + case '\5': /* remove a job from the queue */ + if (!from_remote) { + syslog(LOG_INFO, "illegal request (%d)", *cp); + exit(1); + } + printer = cp; + while (*cp && *cp != ' ') + cp++; + if (!*cp) + break; + *cp++ = '\0'; + person = cp; + while (*cp) { + if (*cp != ' ') { + cp++; + continue; + } + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp == '\0') + break; + if (isdigit(*cp)) { + if (requests >= MAXREQUESTS) + fatal("Too many requests"); + requ[requests++] = atoi(cp); + } else { + if (users >= MAXUSERS) + fatal("Too many users"); + user[users++] = cp; + } + } + rmjob(); + break; + } + fatal("Illegal service request"); + } +} + +/* + * Make a pass through the printcap database and start printing any + * files left from the last time the machine went down. + */ +static void +startup() +{ + char *buf; + register char *cp; + int pid; + + /* + * Restart the daemons. + */ + while (cgetnext(&buf, printcapdb) > 0) { + for (cp = buf; *cp; cp++) + if (*cp == '|' || *cp == ':') { + *cp = '\0'; + break; + } + if ((pid = fork()) < 0) { + syslog(LOG_WARNING, "startup: cannot fork"); + mcleanup(0); + } + if (!pid) { + printer = buf; + cgetclose(); + printjob(); + } + } +} + +#define DUMMY ":nobody::" + +/* + * Check to see if the from host has access to the line printer. + */ +static void +chkhost(f) + struct sockaddr_in *f; +{ + register struct hostent *hp; + register FILE *hostf; + int first = 1; + extern char *inet_ntoa(); + + f->sin_port = ntohs(f->sin_port); + if (f->sin_family != AF_INET || f->sin_port >= IPPORT_RESERVED) + fatal("Malformed from address"); + + /* Need real hostname for temporary filenames */ + hp = gethostbyaddr((char *)&f->sin_addr, + sizeof(struct in_addr), f->sin_family); + if (hp == NULL) + fatal("Host name for your address (%s) unknown", + inet_ntoa(f->sin_addr)); + + (void) strncpy(fromb, hp->h_name, sizeof(fromb)); + from[sizeof(fromb) - 1] = '\0'; + from = fromb; + + hostf = fopen(_PATH_HOSTSEQUIV, "r"); +again: + if (hostf) { + if (__ivaliduser(hostf, f->sin_addr.s_addr, + DUMMY, DUMMY) == 0) { + (void) fclose(hostf); + return; + } + (void) fclose(hostf); + } + if (first == 1) { + first = 0; + hostf = fopen(_PATH_HOSTSLPD, "r"); + goto again; + } + fatal("Your host does not have line printer access"); + /*NOTREACHED*/ +} + + + + + + + + + + + + diff --git a/usr.sbin/lpr/lpd/lpdchar.c b/usr.sbin/lpr/lpd/lpdchar.c new file mode 100644 index 0000000..4a4f5da --- /dev/null +++ b/usr.sbin/lpr/lpd/lpdchar.c @@ -0,0 +1,1066 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)lpdchar.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * Character set for line printer daemon + */ +#include "lp.local.h" + +#define c_______ 0 +#define c______1 01 +#define c_____1_ 02 +#define c____1__ 04 +#define c____11_ 06 +#define c___1___ 010 +#define c___1__1 011 +#define c___1_1_ 012 +#define c___11__ 014 +#define c__1____ 020 +#define c__1__1_ 022 +#define c__1_1__ 024 +#define c__11___ 030 +#define c__111__ 034 +#define c__111_1 035 +#define c__1111_ 036 +#define c__11111 037 +#define c_1_____ 040 +#define c_1____1 041 +#define c_1___1_ 042 +#define c_1__1__ 044 +#define c_1_1___ 050 +#define c_1_1__1 051 +#define c_1_1_1_ 052 +#define c_11____ 060 +#define c_11_11_ 066 +#define c_111___ 070 +#define c_111__1 071 +#define c_111_1_ 072 +#define c_1111__ 074 +#define c_1111_1 075 +#define c_11111_ 076 +#define c_111111 077 +#define c1______ 0100 +#define c1_____1 0101 +#define c1____1_ 0102 +#define c1____11 0103 +#define c1___1__ 0104 +#define c1___1_1 0105 +#define c1___11_ 0106 +#define c1__1___ 0110 +#define c1__1__1 0111 +#define c1__11_1 0115 +#define c1__1111 0117 +#define c1_1____ 0120 +#define c1_1___1 0121 +#define c1_1_1_1 0125 +#define c1_1_11_ 0126 +#define c1_111__ 0134 +#define c1_1111_ 0136 +#define c11____1 0141 +#define c11___1_ 0142 +#define c11___11 0143 +#define c11_1___ 0150 +#define c11_1__1 0151 +#define c111_11_ 0166 +#define c1111___ 0170 +#define c11111__ 0174 +#define c111111_ 0176 +#define c1111111 0177 + +char scnkey[][HEIGHT] = /* this is relatively easy to modify */ + /* just look: */ +{ + { c_______, + c_______, + c_______, + c_______, + c_______, + c_______, + c_______, + c_______, + c_______ }, /* */ + + { c__11___, + c__11___, + c__11___, + c__11___, + c__11___, + c_______, + c_______, + c__11___, + c__11___ }, /* ! */ + + { c_1__1__, + c_1__1__, + c_______, + c_______, + c_______, + c_______, + c_______, + c_______, + c_______ }, /* " */ + + { c_______, + c__1_1__, + c__1_1__, + c1111111, + c__1_1__, + c1111111, + c__1_1__, + c__1_1__, + c_______ }, /* # */ + + { c___1___, + c_11111_, + c1__1__1, + c1__1___, + c_11111_, + c___1__1, + c1__1__1, + c_11111_, + c___1___ }, /* $ */ + + { c_1_____, + c1_1___1, + c_1___1_, + c____1__, + c___1___, + c__1____, + c_1___1_, + c1___1_1, + c_____1_ }, /* % */ + + { c_11____, + c1__1___, + c1___1__, + c_1_1___, + c__1____, + c_1_1__1, + c1___11_, + c1___11_, + c_111__1 }, /* & */ + + { c___11__, + c___11__, + c___1___, + c__1____, + c_______, + c_______, + c_______, + c_______, + c_______ }, /* ' */ + + { c____1__, + c___1___, + c__1____, + c__1____, + c__1____, + c__1____, + c__1____, + c___1___, + c____1__ }, /* ( */ + + { c__1____, + c___1___, + c____1__, + c____1__, + c____1__, + c____1__, + c____1__, + c___1___, + c__1____ }, /* ) */ + + { c_______, + c___1___, + c1__1__1, + c_1_1_1_, + c__111__, + c_1_1_1_, + c1__1__1, + c___1___, + c_______ }, /* * */ + + { c_______, + c___1___, + c___1___, + c___1___, + c1111111, + c___1___, + c___1___, + c___1___, + c_______ }, /* + */ + + { c_______, + c_______, + c_______, + c_______, + c__11___, + c__11___, + c__1____, + c_1_____, + c_______ }, /* , */ + + { c_______, + c_______, + c_______, + c_______, + c1111111, + c_______, + c_______, + c_______, + c_______ }, /* - */ + + { c_______, + c_______, + c_______, + c_______, + c_______, + c_______, + c_______, + c__11___, + c__11___ }, /* . */ + + { c_______, + c______1, + c_____1_, + c____1__, + c___1___, + c__1____, + c_1_____, + c1______, + c_______ }, /* / */ + + { c_11111_, + c1_____1, + c1____11, + c1___1_1, + c1__1__1, + c1_1___1, + c11____1, + c1_____1, + c_11111_ }, /* 0 */ + + { c___1___, + c__11___, + c_1_1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c_11111_ }, /* 1 */ + + { c_11111_, + c1_____1, + c______1, + c_____1_, + c__111__, + c_1_____, + c1______, + c1______, + c1111111 }, /* 2 */ + + { c_11111_, + c1_____1, + c______1, + c______1, + c__1111_, + c______1, + c______1, + c1_____1, + c_11111_ }, /* 3 */ + + { c_____1_, + c____11_, + c___1_1_, + c__1__1_, + c_1___1_, + c1____1_, + c1111111, + c_____1_, + c_____1_ }, /* 4 */ + + { c1111111, + c1______, + c1______, + c11111__, + c_____1_, + c______1, + c______1, + c1____1_, + c_1111__ }, /* 5 */ + + { c__1111_, + c_1_____, + c1______, + c1______, + c1_1111_, + c11____1, + c1_____1, + c1_____1, + c_11111_ }, /* 6 */ + + { c1111111, + c1_____1, + c_____1_, + c____1__, + c___1___, + c__1____, + c__1____, + c__1____, + c__1____ }, /* 7 */ + + { c_11111_, + c1_____1, + c1_____1, + c1_____1, + c_11111_, + c1_____1, + c1_____1, + c1_____1, + c_11111_ }, /* 8 */ + + { c_11111_, + c1_____1, + c1_____1, + c1_____1, + c_111111, + c______1, + c______1, + c1_____1, + c_1111__ }, /* 9 */ + + { c_______, + c_______, + c_______, + c__11___, + c__11___, + c_______, + c_______, + c__11___, + c__11___ }, /* : */ + + + { c__11___, + c__11___, + c_______, + c_______, + c__11___, + c__11___, + c__1____, + c_1_____, + c_______ }, /* ; */ + + { c____1__, + c___1___, + c__1____, + c_1_____, + c1______, + c_1_____, + c__1____, + c___1___, + c____1__ }, /* < */ + + { c_______, + c_______, + c_______, + c1111111, + c_______, + c1111111, + c_______, + c_______, + c_______ }, /* = */ + + { c__1____, + c___1___, + c____1__, + c_____1_, + c______1, + c_____1_, + c____1__, + c___1___, + c__1____ }, /* > */ + + { c__1111_, + c_1____1, + c_1____1, + c______1, + c____11_, + c___1___, + c___1___, + c_______, + c___1___ }, /* ? */ + + { c__1111_, + c_1____1, + c1__11_1, + c1_1_1_1, + c1_1_1_1, + c1_1111_, + c1______, + c_1____1, + c__1111_ }, /* @ */ + + { c__111__, + c_1___1_, + c1_____1, + c1_____1, + c1111111, + c1_____1, + c1_____1, + c1_____1, + c1_____1 }, /* A */ + + { c111111_, + c_1____1, + c_1____1, + c_1____1, + c_11111_, + c_1____1, + c_1____1, + c_1____1, + c111111_ }, /* B */ + + { c__1111_, + c_1____1, + c1______, + c1______, + c1______, + c1______, + c1______, + c_1____1, + c__1111_ }, /* C */ + + { c11111__, + c_1___1_, + c_1____1, + c_1____1, + c_1____1, + c_1____1, + c_1____1, + c_1___1_, + c11111__ }, /* D */ + + { c1111111, + c1______, + c1______, + c1______, + c111111_, + c1______, + c1______, + c1______, + c1111111 }, /* E */ + + { c1111111, + c1______, + c1______, + c1______, + c111111_, + c1______, + c1______, + c1______, + c1______ }, /* F */ + + { c__1111_, + c_1____1, + c1______, + c1______, + c1______, + c1__1111, + c1_____1, + c_1____1, + c__1111_ }, /* G */ + + { c1_____1, + c1_____1, + c1_____1, + c1_____1, + c1111111, + c1_____1, + c1_____1, + c1_____1, + c1_____1 }, /* H */ + + { c_11111_, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c_11111_ }, /* I */ + + { c__11111, + c____1__, + c____1__, + c____1__, + c____1__, + c____1__, + c____1__, + c1___1__, + c_111___ }, /* J */ + + { c1_____1, + c1____1_, + c1___1__, + c1__1___, + c1_1____, + c11_1___, + c1___1__, + c1____1_, + c1_____1 }, /* K */ + + { c1______, + c1______, + c1______, + c1______, + c1______, + c1______, + c1______, + c1______, + c1111111 }, /* L */ + + { c1_____1, + c11___11, + c1_1_1_1, + c1__1__1, + c1_____1, + c1_____1, + c1_____1, + c1_____1, + c1_____1 }, /* M */ + + { c1_____1, + c11____1, + c1_1___1, + c1__1__1, + c1___1_1, + c1____11, + c1_____1, + c1_____1, + c1_____1 }, /* N */ + + { c__111__, + c_1___1_, + c1_____1, + c1_____1, + c1_____1, + c1_____1, + c1_____1, + c_1___1_, + c__111__ }, /* O */ + + { c111111_, + c1_____1, + c1_____1, + c1_____1, + c111111_, + c1______, + c1______, + c1______, + c1______ }, /* P */ + + { c__111__, + c_1___1_, + c1_____1, + c1_____1, + c1_____1, + c1__1__1, + c1___1_1, + c_1___1_, + c__111_1 }, /* Q */ + + { c111111_, + c1_____1, + c1_____1, + c1_____1, + c111111_, + c1__1___, + c1___1__, + c1____1_, + c1_____1 }, /* R */ + + { c_11111_, + c1_____1, + c1______, + c1______, + c_11111_, + c______1, + c______1, + c1_____1, + c_11111_ }, /* S */ + + { c1111111, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___ }, /* T */ + + { c1_____1, + c1_____1, + c1_____1, + c1_____1, + c1_____1, + c1_____1, + c1_____1, + c1_____1, + c_11111_ }, /* U */ + + { c1_____1, + c1_____1, + c1_____1, + c_1___1_, + c_1___1_, + c__1_1__, + c__1_1__, + c___1___, + c___1___ }, /* V */ + + { c1_____1, + c1_____1, + c1_____1, + c1_____1, + c1__1__1, + c1__1__1, + c1_1_1_1, + c11___11, + c1_____1 }, /* W */ + + { c1_____1, + c1_____1, + c_1___1_, + c__1_1__, + c___1___, + c__1_1__, + c_1___1_, + c1_____1, + c1_____1 }, /* X */ + + { c1_____1, + c1_____1, + c_1___1_, + c__1_1__, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___ }, /* Y */ + + { c1111111, + c______1, + c_____1_, + c____1__, + c___1___, + c__1____, + c_1_____, + c1______, + c1111111 }, /* Z */ + + { c_1111__, + c_1_____, + c_1_____, + c_1_____, + c_1_____, + c_1_____, + c_1_____, + c_1_____, + c_1111__ }, /* [ */ + + { c_______, + c1______, + c_1_____, + c__1____, + c___1___, + c____1__, + c_____1_, + c______1, + c_______ }, /* \ */ + + { c__1111_, + c_____1_, + c_____1_, + c_____1_, + c_____1_, + c_____1_, + c_____1_, + c_____1_, + c__1111_ }, /* ] */ + + { c___1___, + c__1_1__, + c_1___1_, + c1_____1, + c_______, + c_______, + c_______, + c_______ }, /* ^ */ + + { c_______, + c_______, + c_______, + c_______, + c_______, + c_______, + c_______, + c1111111, + c_______ }, /* _ */ + + { c__11___, + c__11___, + c___1___, + c____1__, + c_______, + c_______, + c_______, + c_______, + c_______ }, /* ` */ + + { c_______, + c_______, + c_______, + c_1111__, + c_____1_, + c_11111_, + c1_____1, + c1____11, + c_1111_1 }, /* a */ + + { c1______, + c1______, + c1______, + c1_111__, + c11___1_, + c1_____1, + c1_____1, + c11___1_, + c1_111__ }, /* b */ + + { c_______, + c_______, + c_______, + c_1111__, + c1____1_, + c1______, + c1______, + c1____1_, + c_1111__ }, /* c */ + + { c_____1_, + c_____1_, + c_____1_, + c_111_1_, + c1___11_, + c1____1_, + c1____1_, + c1___11_, + c_111_1_ }, /* d */ + + { c_______, + c_______, + c_______, + c_1111__, + c1____1_, + c111111_, + c1______, + c1____1_, + c_1111__ }, /* e */ + + { c___11__, + c__1__1_, + c__1____, + c__1____, + c11111__, + c__1____, + c__1____, + c__1____, + c__1____ }, /* f */ + + { c_111_1_, + c1___11_, + c1____1_, + c1____1_, + c1___11_, + c_111_1_, + c_____1_, + c1____1_, + c_1111__ }, /* g */ + + { c1______, + c1______, + c1______, + c1_111__, + c11___1_, + c1____1_, + c1____1_, + c1____1_, + c1____1_ }, /* h */ + + { c_______, + c___1___, + c_______, + c__11___, + c___1___, + c___1___, + c___1___, + c___1___, + c__111__ }, /* i */ + + { c____11_, + c_____1_, + c_____1_, + c_____1_, + c_____1_, + c_____1_, + c_____1_, + c_1___1_, + c__111__ }, /* j */ + + { c1______, + c1______, + c1______, + c1___1__, + c1__1___, + c1_1____, + c11_1___, + c1___1__, + c1____1_ }, /* k */ + + { c__11___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c__111__ }, /* l */ + + { c_______, + c_______, + c_______, + c1_1_11_, + c11_1__1, + c1__1__1, + c1__1__1, + c1__1__1, + c1__1__1 }, /* m */ + + { c_______, + c_______, + c_______, + c1_111__, + c11___1_, + c1____1_, + c1____1_, + c1____1_, + c1____1_ }, /* n */ + + { c_______, + c_______, + c_______, + c_1111__, + c1____1_, + c1____1_, + c1____1_, + c1____1_, + c_1111__ }, /* o */ + + { c1_111__, + c11___1_, + c1____1_, + c1____1_, + c11___1_, + c1_111__, + c1______, + c1______, + c1______ }, /* p */ + + { c_111_1_, + c1___11_, + c1____1_, + c1____1_, + c1___11_, + c_111_1_, + c_____1_, + c_____1_, + c_____1_ }, /* q */ + + { c_______, + c_______, + c_______, + c1_111__, + c11___1_, + c1______, + c1______, + c1______, + c1______ }, /* r */ + + { c_______, + c_______, + c_______, + c_1111__, + c1____1_, + c_11____, + c___11__, + c1____1_, + c_1111__ }, /* s */ + + { c_______, + c__1____, + c__1____, + c11111__, + c__1____, + c__1____, + c__1____, + c__1__1_, + c___11__ }, /* t */ + + { c_______, + c_______, + c_______, + c1____1_, + c1____1_, + c1____1_, + c1____1_, + c1___11_, + c_111_1_ }, /* u */ + + { c_______, + c_______, + c_______, + c1_____1, + c1_____1, + c1_____1, + c_1___1_, + c__1_1__, + c___1___ }, /* v */ + + { c_______, + c_______, + c_______, + c1_____1, + c1__1__1, + c1__1__1, + c1__1__1, + c1__1__1, + c_11_11_ }, /* w */ + + { c_______, + c_______, + c_______, + c1____1_, + c_1__1__, + c__11___, + c__11___, + c_1__1__, + c1____1_ }, /* x */ + + { c1____1_, + c1____1_, + c1____1_, + c1____1_, + c1___11_, + c_111_1_, + c_____1_, + c1____1_, + c_1111__ }, /* y */ + + { c_______, + c_______, + c_______, + c111111_, + c____1__, + c___1___, + c__1____, + c_1_____, + c111111_ }, /* z */ + + { c___11__, + c__1____, + c__1____, + c__1____, + c_1_____, + c__1____, + c__1____, + c__1____, + c___11__ }, /* } */ + + { c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___, + c___1___ }, /* | */ + + { c__11___, + c____1__, + c____1__, + c____1__, + c_____1_, + c____1__, + c____1__, + c____1__, + c__11___ }, /* } */ + + { c_11____, + c1__1__1, + c____11_, + c_______, + c_______, + c_______, + c_______, + c_______, + c_______ }, /* ~ */ + + { c_1__1__, + c1__1__1, + c__1__1_, + c_1__1__, + c1__1__1, + c__1__1_, + c_1__1__, + c1__1__1, + c__1__1_ } /* rub-out */ +}; diff --git a/usr.sbin/lpr/lpd/printjob.c b/usr.sbin/lpr/lpd/printjob.c new file mode 100644 index 0000000..87c9352 --- /dev/null +++ b/usr.sbin/lpr/lpd/printjob.c @@ -0,0 +1,1377 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)printjob.c 8.2 (Berkeley) 4/16/94"; +#endif /* not lint */ + + +/* + * printjob -- print jobs in the queue. + * + * NOTE: the lock file is used to pass information to lpq and lprm. + * it does not need to be removed because file locks are dynamic. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "lp.local.h" +#include "pathnames.h" +#include "extern.h" + +#define DORETURN 0 /* absorb fork error */ +#define DOABORT 1 /* abort if dofork fails */ + +/* + * Error tokens + */ +#define REPRINT -2 +#define ERROR -1 +#define OK 0 +#define FATALERR 1 +#define NOACCT 2 +#define FILTERERR 3 +#define ACCESS 4 + +static dev_t fdev; /* device of file pointed to by symlink */ +static ino_t fino; /* inode of file pointed to by symlink */ +static FILE *cfp; /* control file */ +static int child; /* id of any filters */ +static int lfd; /* lock file descriptor */ +static int ofd; /* output filter file descriptor */ +static int ofilter; /* id of output filter, if any */ +static int pfd; /* prstatic inter file descriptor */ +static int pid; /* pid of lpd process */ +static int prchild; /* id of pr process */ +static int remote; /* true if sending files to remote */ +static char title[80]; /* ``pr'' title */ +static int tof; /* true if at top of form */ + +static char class[32]; /* classification field */ +static char fromhost[32]; /* user's host machine */ + /* indentation size in static characters */ +static char indent[10] = "-i0"; +static char jobname[100]; /* job or file name */ +static char length[10] = "-l"; /* page length in lines */ +static char logname[32]; /* user's login name */ +static char pxlength[10] = "-y"; /* page length in pixels */ +static char pxwidth[10] = "-x"; /* page width in pixels */ +static char tempfile[] = "errsXXXXXX"; /* file name for filter output */ +static char width[10] = "-w"; /* page width in static characters */ + +static void abortpr __P((int)); +static void banner __P((char *, char *)); +static int dofork __P((int)); +static int dropit __P((int)); +static void init __P((void)); +static void openpr __P((void)); +static int print __P((int, char *)); +static int printit __P((char *)); +static void pstatus __P((const char *, ...)); +static char response __P((void)); +static void scan_out __P((int, char *, int)); +static char *scnline __P((int, char *, int)); +static int sendfile __P((int, char *)); +static int sendit __P((char *)); +static void sendmail __P((char *, int)); +static void setty __P((void)); + +void +printjob() +{ + struct stat stb; + register struct queue *q, **qp; + struct queue **queue; + register int i, nitems; + long pidoff; + int count = 0; + + init(); /* set up capabilities */ + (void) write(1, "", 1); /* ack that daemon is started */ + (void) close(2); /* set up log file */ + if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { + syslog(LOG_ERR, "%s: %m", LF); + (void) open(_PATH_DEVNULL, O_WRONLY); + } + setgid(getegid()); + pid = getpid(); /* for use with lprm */ + setpgrp(0, pid); + signal(SIGHUP, abortpr); + signal(SIGINT, abortpr); + signal(SIGQUIT, abortpr); + signal(SIGTERM, abortpr); + + (void) mktemp(tempfile); + + /* + * uses short form file names + */ + if (chdir(SD) < 0) { + syslog(LOG_ERR, "%s: %m", SD); + exit(1); + } + if (stat(LO, &stb) == 0 && (stb.st_mode & 0100)) + exit(0); /* printing disabled */ + lfd = open(LO, O_WRONLY|O_CREAT, 0644); + if (lfd < 0) { + syslog(LOG_ERR, "%s: %s: %m", printer, LO); + exit(1); + } + if (flock(lfd, LOCK_EX|LOCK_NB) < 0) { + if (errno == EWOULDBLOCK) /* active deamon present */ + exit(0); + syslog(LOG_ERR, "%s: %s: %m", printer, LO); + exit(1); + } + ftruncate(lfd, 0); + /* + * write process id for others to know + */ + sprintf(line, "%u\n", pid); + pidoff = i = strlen(line); + if (write(lfd, line, i) != i) { + syslog(LOG_ERR, "%s: %s: %m", printer, LO); + exit(1); + } + /* + * search the spool directory for work and sort by queue order. + */ + if ((nitems = getq(&queue)) < 0) { + syslog(LOG_ERR, "%s: can't scan %s", printer, SD); + exit(1); + } + if (nitems == 0) /* no work to do */ + exit(0); + if (stb.st_mode & 01) { /* reset queue flag */ + if (fchmod(lfd, stb.st_mode & 0776) < 0) + syslog(LOG_ERR, "%s: %s: %m", printer, LO); + } + openpr(); /* open printer or remote */ +again: + /* + * we found something to do now do it -- + * write the name of the current control file into the lock file + * so the spool queue program can tell what we're working on + */ + for (qp = queue; nitems--; free((char *) q)) { + q = *qp++; + if (stat(q->q_name, &stb) < 0) + continue; + restart: + (void) lseek(lfd, (off_t)pidoff, 0); + (void) sprintf(line, "%s\n", q->q_name); + i = strlen(line); + if (write(lfd, line, i) != i) + syslog(LOG_ERR, "%s: %s: %m", printer, LO); + if (!remote) + i = printit(q->q_name); + else + i = sendit(q->q_name); + /* + * Check to see if we are supposed to stop printing or + * if we are to rebuild the queue. + */ + if (fstat(lfd, &stb) == 0) { + /* stop printing before starting next job? */ + if (stb.st_mode & 0100) + goto done; + /* rebuild queue (after lpc topq) */ + if (stb.st_mode & 01) { + for (free((char *) q); nitems--; free((char *) q)) + q = *qp++; + if (fchmod(lfd, stb.st_mode & 0776) < 0) + syslog(LOG_WARNING, "%s: %s: %m", + printer, LO); + break; + } + } + if (i == OK) /* file ok and printed */ + count++; + else if (i == REPRINT) { /* try reprinting the job */ + syslog(LOG_INFO, "restarting %s", printer); + if (ofilter > 0) { + kill(ofilter, SIGCONT); /* to be sure */ + (void) close(ofd); + while ((i = wait(0)) > 0 && i != ofilter) + ; + ofilter = 0; + } + (void) close(pfd); /* close printer */ + if (ftruncate(lfd, pidoff) < 0) + syslog(LOG_WARNING, "%s: %s: %m", printer, LO); + openpr(); /* try to reopen printer */ + goto restart; + } + } + free((char *) queue); + /* + * search the spool directory for more work. + */ + if ((nitems = getq(&queue)) < 0) { + syslog(LOG_ERR, "%s: can't scan %s", printer, SD); + exit(1); + } + if (nitems == 0) { /* no more work to do */ + done: + if (count > 0) { /* Files actually printed */ + if (!SF && !tof) + (void) write(ofd, FF, strlen(FF)); + if (TR != NULL) /* output trailer */ + (void) write(ofd, TR, strlen(TR)); + } + (void) unlink(tempfile); + exit(0); + } + goto again; +} + +char fonts[4][50]; /* fonts for troff */ + +char ifonts[4][40] = { + _PATH_VFONTR, + _PATH_VFONTI, + _PATH_VFONTB, + _PATH_VFONTS, +}; + +/* + * The remaining part is the reading of the control file (cf) + * and performing the various actions. + */ +static int +printit(file) + char *file; +{ + register int i; + char *cp; + int bombed = OK; + + /* + * open control file; ignore if no longer there. + */ + if ((cfp = fopen(file, "r")) == NULL) { + syslog(LOG_INFO, "%s: %s: %m", printer, file); + return(OK); + } + /* + * Reset troff fonts. + */ + for (i = 0; i < 4; i++) + strcpy(fonts[i], ifonts[i]); + sprintf(&width[2], "%d", PW); + strcpy(indent+2, "0"); + + /* + * read the control file for work to do + * + * file format -- first character in the line is a command + * rest of the line is the argument. + * valid commands are: + * + * S -- "stat info" for symbolic link protection + * J -- "job name" on banner page + * C -- "class name" on banner page + * L -- "literal" user's name to print on banner + * T -- "title" for pr + * H -- "host name" of machine where lpr was done + * P -- "person" user's login name + * I -- "indent" amount to indent output + * f -- "file name" name of text file to print + * l -- "file name" text file with control chars + * p -- "file name" text file to print with pr(1) + * t -- "file name" troff(1) file to print + * n -- "file name" ditroff(1) file to print + * d -- "file name" dvi file to print + * g -- "file name" plot(1G) file to print + * v -- "file name" plain raster file to print + * c -- "file name" cifplot file to print + * 1 -- "R font file" for troff + * 2 -- "I font file" for troff + * 3 -- "B font file" for troff + * 4 -- "S font file" for troff + * N -- "name" of file (used by lpq) + * U -- "unlink" name of file to remove + * (after we print it. (Pass 2 only)). + * M -- "mail" to user when done printing + * + * getline reads a line and expands tabs to blanks + */ + + /* pass 1 */ + + while (getline(cfp)) + switch (line[0]) { + case 'H': + strcpy(fromhost, line+1); + if (class[0] == '\0') + strncpy(class, line+1, sizeof(class)-1); + continue; + + case 'P': + strncpy(logname, line+1, sizeof(logname)-1); + if (RS) { /* restricted */ + if (getpwnam(logname) == NULL) { + bombed = NOACCT; + sendmail(line+1, bombed); + goto pass2; + } + } + continue; + + case 'S': + cp = line+1; + i = 0; + while (*cp >= '0' && *cp <= '9') + i = i * 10 + (*cp++ - '0'); + fdev = i; + cp++; + i = 0; + while (*cp >= '0' && *cp <= '9') + i = i * 10 + (*cp++ - '0'); + fino = i; + continue; + + case 'J': + if (line[1] != '\0') + strncpy(jobname, line+1, sizeof(jobname)-1); + else + strcpy(jobname, " "); + continue; + + case 'C': + if (line[1] != '\0') + strncpy(class, line+1, sizeof(class)-1); + else if (class[0] == '\0') + gethostname(class, sizeof(class)); + continue; + + case 'T': /* header title for pr */ + strncpy(title, line+1, sizeof(title)-1); + continue; + + case 'L': /* identification line */ + if (!SH && !HL) + banner(line+1, jobname); + continue; + + case '1': /* troff fonts */ + case '2': + case '3': + case '4': + if (line[1] != '\0') + strcpy(fonts[line[0]-'1'], line+1); + continue; + + case 'W': /* page width */ + strncpy(width+2, line+1, sizeof(width)-3); + continue; + + case 'I': /* indent amount */ + strncpy(indent+2, line+1, sizeof(indent)-3); + continue; + + default: /* some file to print */ + switch (i = print(line[0], line+1)) { + case ERROR: + if (bombed == OK) + bombed = FATALERR; + break; + case REPRINT: + (void) fclose(cfp); + return(REPRINT); + case FILTERERR: + case ACCESS: + bombed = i; + sendmail(logname, bombed); + } + title[0] = '\0'; + continue; + + case 'N': + case 'U': + case 'M': + continue; + } + + /* pass 2 */ + +pass2: + fseek(cfp, 0L, 0); + while (getline(cfp)) + switch (line[0]) { + case 'L': /* identification line */ + if (!SH && HL) + banner(line+1, jobname); + continue; + + case 'M': + if (bombed < NOACCT) /* already sent if >= NOACCT */ + sendmail(line+1, bombed); + continue; + + case 'U': + (void) unlink(line+1); + } + /* + * clean-up in case another control file exists + */ + (void) fclose(cfp); + (void) unlink(file); + return(bombed == OK ? OK : ERROR); +} + +/* + * Print a file. + * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}. + * Return -1 if a non-recoverable error occured, + * 2 if the filter detected some errors (but printed the job anyway), + * 1 if we should try to reprint this job and + * 0 if all is well. + * Note: all filters take stdin as the file, stdout as the printer, + * stderr as the log file, and must not ignore SIGINT. + */ +static int +print(format, file) + int format; + char *file; +{ + register int n; + register char *prog; + int fi, fo; + FILE *fp; + char *av[15], buf[BUFSIZ]; + int pid, p[2], stopped = 0; + union wait status; + struct stat stb; + + if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0) + return(ERROR); + /* + * Check to see if data file is a symbolic link. If so, it should + * still point to the same file or someone is trying to print + * something he shouldn't. + */ + if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 && + (stb.st_dev != fdev || stb.st_ino != fino)) + return(ACCESS); + if (!SF && !tof) { /* start on a fresh page */ + (void) write(ofd, FF, strlen(FF)); + tof = 1; + } + if (IF == NULL && (format == 'f' || format == 'l')) { + tof = 0; + while ((n = read(fi, buf, BUFSIZ)) > 0) + if (write(ofd, buf, n) != n) { + (void) close(fi); + return(REPRINT); + } + (void) close(fi); + return(OK); + } + switch (format) { + case 'p': /* print file using 'pr' */ + if (IF == NULL) { /* use output filter */ + prog = _PATH_PR; + av[0] = "pr"; + av[1] = width; + av[2] = length; + av[3] = "-h"; + av[4] = *title ? title : " "; + av[5] = 0; + fo = ofd; + goto start; + } + pipe(p); + if ((prchild = dofork(DORETURN)) == 0) { /* child */ + dup2(fi, 0); /* file is stdin */ + dup2(p[1], 1); /* pipe is stdout */ + for (n = 3; n < NOFILE; n++) + (void) close(n); + execl(_PATH_PR, "pr", width, length, + "-h", *title ? title : " ", 0); + syslog(LOG_ERR, "cannot execl %s", _PATH_PR); + exit(2); + } + (void) close(p[1]); /* close output side */ + (void) close(fi); + if (prchild < 0) { + prchild = 0; + (void) close(p[0]); + return(ERROR); + } + fi = p[0]; /* use pipe for input */ + case 'f': /* print plain text file */ + prog = IF; + av[1] = width; + av[2] = length; + av[3] = indent; + n = 4; + break; + case 'l': /* like 'f' but pass control characters */ + prog = IF; + av[1] = "-c"; + av[2] = width; + av[3] = length; + av[4] = indent; + n = 5; + break; + case 'r': /* print a fortran text file */ + prog = RF; + av[1] = width; + av[2] = length; + n = 3; + break; + case 't': /* print troff output */ + case 'n': /* print ditroff output */ + case 'd': /* print tex output */ + (void) unlink(".railmag"); + if ((fo = creat(".railmag", FILMOD)) < 0) { + syslog(LOG_ERR, "%s: cannot create .railmag", printer); + (void) unlink(".railmag"); + } else { + for (n = 0; n < 4; n++) { + if (fonts[n][0] != '/') + (void) write(fo, _PATH_VFONT, + sizeof(_PATH_VFONT) - 1); + (void) write(fo, fonts[n], strlen(fonts[n])); + (void) write(fo, "\n", 1); + } + (void) close(fo); + } + prog = (format == 't') ? TF : (format == 'n') ? NF : DF; + av[1] = pxwidth; + av[2] = pxlength; + n = 3; + break; + case 'c': /* print cifplot output */ + prog = CF; + av[1] = pxwidth; + av[2] = pxlength; + n = 3; + break; + case 'g': /* print plot(1G) output */ + prog = GF; + av[1] = pxwidth; + av[2] = pxlength; + n = 3; + break; + case 'v': /* print raster output */ + prog = VF; + av[1] = pxwidth; + av[2] = pxlength; + n = 3; + break; + default: + (void) close(fi); + syslog(LOG_ERR, "%s: illegal format character '%c'", + printer, format); + return(ERROR); + } + if ((av[0] = rindex(prog, '/')) != NULL) + av[0]++; + else + av[0] = prog; + av[n++] = "-n"; + av[n++] = logname; + av[n++] = "-h"; + av[n++] = fromhost; + av[n++] = AF; + av[n] = 0; + fo = pfd; + if (ofilter > 0) { /* stop output filter */ + write(ofd, "\031\1", 2); + while ((pid = + wait3((int *)&status, WUNTRACED, 0)) > 0 && pid != ofilter) + ; + if (status.w_stopval != WSTOPPED) { + (void) close(fi); + syslog(LOG_WARNING, "%s: output filter died (%d)", + printer, status.w_retcode); + return(REPRINT); + } + stopped++; + } +start: + if ((child = dofork(DORETURN)) == 0) { /* child */ + dup2(fi, 0); + dup2(fo, 1); + n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664); + if (n >= 0) + dup2(n, 2); + for (n = 3; n < NOFILE; n++) + (void) close(n); + execv(prog, av); + syslog(LOG_ERR, "cannot execv %s", prog); + exit(2); + } + (void) close(fi); + if (child < 0) + status.w_retcode = 100; + else + while ((pid = wait((int *)&status)) > 0 && pid != child) + ; + child = 0; + prchild = 0; + if (stopped) { /* restart output filter */ + if (kill(ofilter, SIGCONT) < 0) { + syslog(LOG_ERR, "cannot restart output filter"); + exit(1); + } + } + tof = 0; + + /* Copy filter output to "lf" logfile */ + if (fp = fopen(tempfile, "r")) { + while (fgets(buf, sizeof(buf), fp)) + fputs(buf, stderr); + fclose(fp); + } + + if (!WIFEXITED(status)) { + syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)", + printer, format, status.w_termsig); + return(ERROR); + } + switch (status.w_retcode) { + case 0: + tof = 1; + return(OK); + case 1: + return(REPRINT); + default: + syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)", + printer, format, status.w_retcode); + case 2: + return(ERROR); + } +} + +/* + * Send the daemon control file (cf) and any data files. + * Return -1 if a non-recoverable error occured, 1 if a recoverable error and + * 0 if all is well. + */ +static int +sendit(file) + char *file; +{ + register int i, err = OK; + char *cp, last[BUFSIZ]; + + /* + * open control file + */ + if ((cfp = fopen(file, "r")) == NULL) + return(OK); + /* + * read the control file for work to do + * + * file format -- first character in the line is a command + * rest of the line is the argument. + * commands of interest are: + * + * a-z -- "file name" name of file to print + * U -- "unlink" name of file to remove + * (after we print it. (Pass 2 only)). + */ + + /* + * pass 1 + */ + while (getline(cfp)) { + again: + if (line[0] == 'S') { + cp = line+1; + i = 0; + while (*cp >= '0' && *cp <= '9') + i = i * 10 + (*cp++ - '0'); + fdev = i; + cp++; + i = 0; + while (*cp >= '0' && *cp <= '9') + i = i * 10 + (*cp++ - '0'); + fino = i; + continue; + } + if (line[0] >= 'a' && line[0] <= 'z') { + strcpy(last, line); + while (i = getline(cfp)) + if (strcmp(last, line)) + break; + switch (sendfile('\3', last+1)) { + case OK: + if (i) + goto again; + break; + case REPRINT: + (void) fclose(cfp); + return(REPRINT); + case ACCESS: + sendmail(logname, ACCESS); + case ERROR: + err = ERROR; + } + break; + } + } + if (err == OK && sendfile('\2', file) > 0) { + (void) fclose(cfp); + return(REPRINT); + } + /* + * pass 2 + */ + fseek(cfp, 0L, 0); + while (getline(cfp)) + if (line[0] == 'U') + (void) unlink(line+1); + /* + * clean-up in case another control file exists + */ + (void) fclose(cfp); + (void) unlink(file); + return(err); +} + +/* + * Send a data file to the remote machine and spool it. + * Return positive if we should try resending. + */ +static int +sendfile(type, file) + int type; + char *file; +{ + register int f, i, amt; + struct stat stb; + char buf[BUFSIZ]; + int sizerr, resp; + + if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0) + return(ERROR); + /* + * Check to see if data file is a symbolic link. If so, it should + * still point to the same file or someone is trying to print something + * he shouldn't. + */ + if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 && + (stb.st_dev != fdev || stb.st_ino != fino)) + return(ACCESS); + (void) sprintf(buf, "%c%qd %s\n", type, stb.st_size, file); + amt = strlen(buf); + for (i = 0; ; i++) { + if (write(pfd, buf, amt) != amt || + (resp = response()) < 0 || resp == '\1') { + (void) close(f); + return(REPRINT); + } else if (resp == '\0') + break; + if (i == 0) + pstatus("no space on remote; waiting for queue to drain"); + if (i == 10) + syslog(LOG_ALERT, "%s: can't send to %s; queue full", + printer, RM); + sleep(5 * 60); + } + if (i) + pstatus("sending to %s", RM); + sizerr = 0; + for (i = 0; i < stb.st_size; i += BUFSIZ) { + amt = BUFSIZ; + if (i + amt > stb.st_size) + amt = stb.st_size - i; + if (sizerr == 0 && read(f, buf, amt) != amt) + sizerr = 1; + if (write(pfd, buf, amt) != amt) { + (void) close(f); + return(REPRINT); + } + } + + + + + (void) close(f); + if (sizerr) { + syslog(LOG_INFO, "%s: %s: changed size", printer, file); + /* tell recvjob to ignore this file */ + (void) write(pfd, "\1", 1); + return(ERROR); + } + if (write(pfd, "", 1) != 1 || response()) + return(REPRINT); + return(OK); +} + +/* + * Check to make sure there have been no errors and that both programs + * are in sync with eachother. + * Return non-zero if the connection was lost. + */ +static char +response() +{ + char resp; + + if (read(pfd, &resp, 1) != 1) { + syslog(LOG_INFO, "%s: lost connection", printer); + return(-1); + } + return(resp); +} + +/* + * Banner printing stuff + */ +static void +banner(name1, name2) + char *name1, *name2; +{ + time_t tvec; + extern char *ctime(); + + time(&tvec); + if (!SF && !tof) + (void) write(ofd, FF, strlen(FF)); + if (SB) { /* short banner only */ + if (class[0]) { + (void) write(ofd, class, strlen(class)); + (void) write(ofd, ":", 1); + } + (void) write(ofd, name1, strlen(name1)); + (void) write(ofd, " Job: ", 7); + (void) write(ofd, name2, strlen(name2)); + (void) write(ofd, " Date: ", 8); + (void) write(ofd, ctime(&tvec), 24); + (void) write(ofd, "\n", 1); + } else { /* normal banner */ + (void) write(ofd, "\n\n\n", 3); + scan_out(ofd, name1, '\0'); + (void) write(ofd, "\n\n", 2); + scan_out(ofd, name2, '\0'); + if (class[0]) { + (void) write(ofd,"\n\n\n",3); + scan_out(ofd, class, '\0'); + } + (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob: ", 15); + (void) write(ofd, name2, strlen(name2)); + (void) write(ofd, "\n\t\t\t\t\tDate: ", 12); + (void) write(ofd, ctime(&tvec), 24); + (void) write(ofd, "\n", 1); + } + if (!SF) + (void) write(ofd, FF, strlen(FF)); + tof = 1; +} + +static char * +scnline(key, p, c) + register int key; + register char *p; + int c; +{ + register scnwidth; + + for (scnwidth = WIDTH; --scnwidth;) { + key <<= 1; + *p++ = key & 0200 ? c : BACKGND; + } + return (p); +} + +#define TRC(q) (((q)-' ')&0177) + +static void +scan_out(scfd, scsp, dlm) + int scfd, dlm; + char *scsp; +{ + register char *strp; + register nchrs, j; + char outbuf[LINELEN+1], *sp, c, cc; + int d, scnhgt; + extern char scnkey[][HEIGHT]; /* in lpdchar.c */ + + for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) { + strp = &outbuf[0]; + sp = scsp; + for (nchrs = 0; ; ) { + d = dropit(c = TRC(cc = *sp++)); + if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d)) + for (j = WIDTH; --j;) + *strp++ = BACKGND; + else + strp = scnline(scnkey[c][scnhgt-1-d], strp, cc); + if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1) + break; + *strp++ = BACKGND; + *strp++ = BACKGND; + } + while (*--strp == BACKGND && strp >= outbuf) + ; + strp++; + *strp++ = '\n'; + (void) write(scfd, outbuf, strp-outbuf); + } +} + +static int +dropit(c) + int c; +{ + switch(c) { + + case TRC('_'): + case TRC(';'): + case TRC(','): + case TRC('g'): + case TRC('j'): + case TRC('p'): + case TRC('q'): + case TRC('y'): + return (DROP); + + default: + return (0); + } +} + +/* + * sendmail --- + * tell people about job completion + */ +static void +sendmail(user, bombed) + char *user; + int bombed; +{ + register int i; + int p[2], s; + register char *cp; + char buf[100]; + struct stat stb; + FILE *fp; + + pipe(p); + if ((s = dofork(DORETURN)) == 0) { /* child */ + dup2(p[0], 0); + for (i = 3; i < NOFILE; i++) + (void) close(i); + if ((cp = rindex(_PATH_SENDMAIL, '/')) != NULL) + cp++; + else + cp = _PATH_SENDMAIL; + sprintf(buf, "%s@%s", user, fromhost); + execl(_PATH_SENDMAIL, cp, buf, 0); + exit(0); + } else if (s > 0) { /* parent */ + dup2(p[1], 1); + printf("To: %s@%s\n", user, fromhost); + printf("Subject: printer job\n\n"); + printf("Your printer job "); + if (*jobname) + printf("(%s) ", jobname); + switch (bombed) { + case OK: + printf("\ncompleted successfully\n"); + break; + default: + case FATALERR: + printf("\ncould not be printed\n"); + break; + case NOACCT: + printf("\ncould not be printed without an account on %s\n", host); + break; + case FILTERERR: + if (stat(tempfile, &stb) < 0 || stb.st_size == 0 || + (fp = fopen(tempfile, "r")) == NULL) { + printf("\nwas printed but had some errors\n"); + break; + } + printf("\nwas printed but had the following errors:\n"); + while ((i = getc(fp)) != EOF) + putchar(i); + (void) fclose(fp); + break; + case ACCESS: + printf("\nwas not printed because it was not linked to the original file\n"); + } + fflush(stdout); + (void) close(1); + } + (void) close(p[0]); + (void) close(p[1]); + wait(&s); +} + +/* + * dofork - fork with retries on failure + */ +static int +dofork(action) + int action; +{ + register int i, pid; + + for (i = 0; i < 20; i++) { + if ((pid = fork()) < 0) { + sleep((unsigned)(i*i)); + continue; + } + /* + * Child should run as daemon instead of root + */ + if (pid == 0) + setuid(DU); + return(pid); + } + syslog(LOG_ERR, "can't fork"); + + switch (action) { + case DORETURN: + return (-1); + default: + syslog(LOG_ERR, "bad action (%d) to dofork", action); + /*FALL THRU*/ + case DOABORT: + exit(1); + } + /*NOTREACHED*/ +} + +/* + * Kill child processes to abort current job. + */ +static void +abortpr(signo) + int signo; +{ + (void) unlink(tempfile); + kill(0, SIGINT); + if (ofilter > 0) + kill(ofilter, SIGCONT); + while (wait(NULL) > 0) + ; + exit(0); +} + +static void +init() +{ + int status; + char *s; + + if ((status = cgetent(&bp, printcapdb, printer)) == -2) { + syslog(LOG_ERR, "can't open printer description file"); + exit(1); + } else if (status == -1) { + syslog(LOG_ERR, "unknown printer: %s", printer); + exit(1); + } else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + if (cgetstr(bp, "lp", &LP) == -1) + LP = _PATH_DEFDEVLP; + if (cgetstr(bp, "rp", &RP) == -1) + RP = DEFLP; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + if (cgetstr(bp, "st", &ST) == -1) + ST = DEFSTAT; + if (cgetstr(bp, "lf", &LF) == -1) + LF = _PATH_CONSOLE; + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetnum(bp, "du", &DU) < 0) + DU = DEFUID; + if (cgetstr(bp,"ff", &FF) == -1) + FF = DEFFF; + if (cgetnum(bp, "pw", &PW) < 0) + PW = DEFWIDTH; + sprintf(&width[2], "%d", PW); + if (cgetnum(bp, "pl", &PL) < 0) + PL = DEFLENGTH; + sprintf(&length[2], "%d", PL); + if (cgetnum(bp,"px", &PX) < 0) + PX = 0; + sprintf(&pxwidth[2], "%d", PX); + if (cgetnum(bp, "py", &PY) < 0) + PY = 0; + sprintf(&pxlength[2], "%d", PY); + cgetstr(bp, "rm", &RM); + if (s = checkremote()) + syslog(LOG_WARNING, s); + + cgetstr(bp, "af", &AF); + cgetstr(bp, "of", &OF); + cgetstr(bp, "if", &IF); + cgetstr(bp, "rf", &RF); + cgetstr(bp, "tf", &TF); + cgetstr(bp, "nf", &NF); + cgetstr(bp, "df", &DF); + cgetstr(bp, "gf", &GF); + cgetstr(bp, "vf", &VF); + cgetstr(bp, "cf", &CF); + cgetstr(bp, "tr", &TR); + + RS = (cgetcap(bp, "rs", ':') != NULL); + SF = (cgetcap(bp, "sf", ':') != NULL); + SH = (cgetcap(bp, "sh", ':') != NULL); + SB = (cgetcap(bp, "sb", ':') != NULL); + HL = (cgetcap(bp, "hl", ':') != NULL); + RW = (cgetcap(bp, "rw", ':') != NULL); + + cgetnum(bp, "br", &BR); + if (cgetnum(bp, "fc", &FC) < 0) + FC = 0; + if (cgetnum(bp, "fs", &FS) < 0) + FS = 0; + if (cgetnum(bp, "xc", &XC) < 0) + XC = 0; + if (cgetnum(bp, "xs", &XS) < 0) + XS = 0; + + tof = (cgetcap(bp, "fo", ':') == NULL); +} + +/* + * Acquire line printer or remote connection. + */ +static void +openpr() +{ + register int i, n; + int resp; + + if (!sendtorem && *LP) { + for (i = 1; ; i = i < 32 ? i << 1 : i) { + pfd = open(LP, RW ? O_RDWR : O_WRONLY); + if (pfd >= 0) + break; + if (errno == ENOENT) { + syslog(LOG_ERR, "%s: %m", LP); + exit(1); + } + if (i == 1) + pstatus("waiting for %s to become ready (offline ?)", printer); + sleep(i); + } + if (isatty(pfd)) + setty(); + pstatus("%s is ready and printing", printer); + } else if (RM != NULL) { + for (i = 1; ; i = i < 256 ? i << 1 : i) { + resp = -1; + pfd = getport(RM); + if (pfd >= 0) { + (void) sprintf(line, "\2%s\n", RP); + n = strlen(line); + if (write(pfd, line, n) == n && + (resp = response()) == '\0') + break; + (void) close(pfd); + } + if (i == 1) { + if (resp < 0) + pstatus("waiting for %s to come up", RM); + else { + pstatus("waiting for queue to be enabled on %s", RM); + i = 256; + } + } + sleep(i); + } + pstatus("sending to %s", RM); + remote = 1; + } else { + syslog(LOG_ERR, "%s: no line printer device or host name", + printer); + exit(1); + } + /* + * Start up an output filter, if needed. + */ + if (!remote && OF) { + int p[2]; + char *cp; + + pipe(p); + if ((ofilter = dofork(DOABORT)) == 0) { /* child */ + dup2(p[0], 0); /* pipe is std in */ + dup2(pfd, 1); /* printer is std out */ + for (i = 3; i < NOFILE; i++) + (void) close(i); + if ((cp = rindex(OF, '/')) == NULL) + cp = OF; + else + cp++; + execl(OF, cp, width, length, 0); + syslog(LOG_ERR, "%s: %s: %m", printer, OF); + exit(1); + } + (void) close(p[0]); /* close input side */ + ofd = p[1]; /* use pipe for output */ + } else { + ofd = pfd; + ofilter = 0; + } +} + +struct bauds { + int baud; + int speed; +} bauds[] = { + 50, B50, + 75, B75, + 110, B110, + 134, B134, + 150, B150, + 200, B200, + 300, B300, + 600, B600, + 1200, B1200, + 1800, B1800, + 2400, B2400, + 4800, B4800, + 9600, B9600, + 19200, EXTA, + 38400, EXTB, + 0, 0 +}; + +/* + * setup tty lines. + */ +static void +setty() +{ + struct sgttyb ttybuf; + register struct bauds *bp; + + if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) { + syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer); + exit(1); + } + if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) { + syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer); + exit(1); + } + if (BR > 0) { + for (bp = bauds; bp->baud; bp++) + if (BR == bp->baud) + break; + if (!bp->baud) { + syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR); + exit(1); + } + ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed; + } + ttybuf.sg_flags &= ~FC; + ttybuf.sg_flags |= FS; + if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) { + syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer); + exit(1); + } + if (XC) { + if (ioctl(pfd, TIOCLBIC, &XC) < 0) { + syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer); + exit(1); + } + } + if (XS) { + if (ioctl(pfd, TIOCLBIS, &XS) < 0) { + syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer); + exit(1); + } + } +} + +#if __STDC__ +#include +#else +#include +#endif + +void +#if __STDC__ +pstatus(const char *msg, ...) +#else +pstatus(msg, va_alist) + char *msg; + va_dcl +#endif +{ + register int fd; + char buf[BUFSIZ]; + va_list ap; +#if __STDC__ + va_start(ap, msg); +#else + va_start(ap); +#endif + + umask(0); + fd = open(ST, O_WRONLY|O_CREAT, 0664); + if (fd < 0 || flock(fd, LOCK_EX) < 0) { + syslog(LOG_ERR, "%s: %s: %m", printer, ST); + exit(1); + } + ftruncate(fd, 0); + (void)vsnprintf(buf, sizeof(buf), msg, ap); + va_end(ap); + strcat(buf, "\n"); + (void) write(fd, buf, strlen(buf)); + (void) close(fd); +} diff --git a/usr.sbin/lpr/lpd/recvjob.c b/usr.sbin/lpr/lpd/recvjob.c new file mode 100644 index 0000000..67a6183 --- /dev/null +++ b/usr.sbin/lpr/lpd/recvjob.c @@ -0,0 +1,358 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)recvjob.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * Receive printer jobs from the network, queue them and + * start the printer daemon. + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "lp.local.h" +#include "extern.h" +#include "pathnames.h" + +#define ack() (void) write(1, sp, 1); + +static char dfname[40]; /* data files */ +static int minfree; /* keep at least minfree blocks available */ +static char *sp = ""; +static char tfname[40]; /* tmp copy of cf before linking */ + +static int chksize __P((int)); +static void frecverr __P((const char *, ...)); +static int noresponse __P((void)); +static void rcleanup __P((int)); +static int read_number __P((char *)); +static int readfile __P((char *, int)); +static int readjob __P((void)); + + +void +recvjob() +{ + struct stat stb; + int status; + + /* + * Perform lookup for printer name or abbreviation + */ + if ((status = cgetent(&bp, printcapdb, printer)) == -2) + frecverr("cannot open printer description file"); + else if (status == -1) + frecverr("unknown printer %s", printer); + else if (status == -3) + fatal("potential reference loop detected in printcap file"); + + if (cgetstr(bp, "lf", &LF) == -1) + LF = _PATH_CONSOLE; + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + + (void) close(2); /* set up log file */ + if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { + syslog(LOG_ERR, "%s: %m", LF); + (void) open(_PATH_DEVNULL, O_WRONLY); + } + + if (chdir(SD) < 0) + frecverr("%s: %s: %m", printer, SD); + if (stat(LO, &stb) == 0) { + if (stb.st_mode & 010) { + /* queue is disabled */ + putchar('\1'); /* return error code */ + exit(1); + } + } else if (stat(SD, &stb) < 0) + frecverr("%s: %s: %m", printer, SD); + minfree = 2 * read_number("minfree"); /* scale KB to 512 blocks */ + signal(SIGTERM, rcleanup); + signal(SIGPIPE, rcleanup); + + if (readjob()) + printjob(); +} + +/* + * Read printer jobs sent by lpd and copy them to the spooling directory. + * Return the number of jobs successfully transfered. + */ +static int +readjob() +{ + register int size, nfiles; + register char *cp; + + ack(); + nfiles = 0; + for (;;) { + /* + * Read a command to tell us what to do + */ + cp = line; + do { + if ((size = read(1, cp, 1)) != 1) { + if (size < 0) + frecverr("%s: Lost connection",printer); + return(nfiles); + } + } while (*cp++ != '\n'); + *--cp = '\0'; + cp = line; + switch (*cp++) { + case '\1': /* cleanup because data sent was bad */ + rcleanup(0); + continue; + + case '\2': /* read cf file */ + size = 0; + while (*cp >= '0' && *cp <= '9') + size = size * 10 + (*cp++ - '0'); + if (*cp++ != ' ') + break; + /* + * host name has been authenticated, we use our + * view of the host name since we may be passed + * something different than what gethostbyaddr() + * returns + */ + strcpy(cp + 6, from); + strcpy(tfname, cp); + tfname[0] = 't'; + if (!chksize(size)) { + (void) write(1, "\2", 1); + continue; + } + if (!readfile(tfname, size)) { + rcleanup(0); + continue; + } + if (link(tfname, cp) < 0) + frecverr("%s: %m", tfname); + (void) unlink(tfname); + tfname[0] = '\0'; + nfiles++; + continue; + + case '\3': /* read df file */ + size = 0; + while (*cp >= '0' && *cp <= '9') + size = size * 10 + (*cp++ - '0'); + if (*cp++ != ' ') + break; + if (!chksize(size)) { + (void) write(1, "\2", 1); + continue; + } + (void) strcpy(dfname, cp); + if (index(dfname, '/')) + frecverr("readjob: %s: illegal path name", + dfname); + (void) readfile(dfname, size); + continue; + } + frecverr("protocol screwup: %s", line); + } +} + +/* + * Read files send by lpd and copy them to the spooling directory. + */ +static int +readfile(file, size) + char *file; + int size; +{ + register char *cp; + char buf[BUFSIZ]; + register int i, j, amt; + int fd, err; + + fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD); + if (fd < 0) + frecverr("readfile: %s: illegal path name: %m", file); + ack(); + err = 0; + for (i = 0; i < size; i += BUFSIZ) { + amt = BUFSIZ; + cp = buf; + if (i + amt > size) + amt = size - i; + do { + j = read(1, cp, amt); + if (j <= 0) + frecverr("Lost connection"); + amt -= j; + cp += j; + } while (amt > 0); + amt = BUFSIZ; + if (i + amt > size) + amt = size - i; + if (write(fd, buf, amt) != amt) { + err++; + break; + } + } + (void) close(fd); + if (err) + frecverr("%s: write error", file); + if (noresponse()) { /* file sent had bad data in it */ + (void) unlink(file); + return(0); + } + ack(); + return(1); +} + +static int +noresponse() +{ + char resp; + + if (read(1, &resp, 1) != 1) + frecverr("Lost connection"); + if (resp == '\0') + return(0); + return(1); +} + +/* + * Check to see if there is enough space on the disk for size bytes. + * 1 == OK, 0 == Not OK. + */ +static int +chksize(size) + int size; +{ + int spacefree; + struct statfs sfb; + + if (statfs(".", &sfb) < 0) { + syslog(LOG_ERR, "%s: %m", "statfs(\".\")"); + return (1); + } + spacefree = sfb.f_bavail * (sfb.f_bsize / 512); + size = (size + 511) / 512; + if (minfree + size > spacefree) + return(0); + return(1); +} + +static int +read_number(fn) + char *fn; +{ + char lin[80]; + register FILE *fp; + + if ((fp = fopen(fn, "r")) == NULL) + return (0); + if (fgets(lin, 80, fp) == NULL) { + fclose(fp); + return (0); + } + fclose(fp); + return (atoi(lin)); +} + +/* + * Remove all the files associated with the current job being transfered. + */ +static void +rcleanup(signo) + int signo; +{ + if (tfname[0]) + (void) unlink(tfname); + if (dfname[0]) + do { + do + (void) unlink(dfname); + while (dfname[2]-- != 'A'); + dfname[2] = 'z'; + } while (dfname[0]-- != 'd'); + dfname[0] = '\0'; +} + +#if __STDC__ +#include +#else +#include +#endif + +static void +#if __STDC__ +frecverr(const char *msg, ...) +#else +frecverr(msg, va_alist) + char *msg; + va_dcl +#endif +{ + extern char *fromb; + va_list ap; +#if __STDC__ + va_start(ap, msg); +#else + va_start(ap); +#endif + rcleanup(0); + syslog(LOG_ERR, "%s", fromb); + vsyslog(LOG_ERR, msg, ap); + va_end(ap); + putchar('\1'); /* return error code */ + exit(1); +} diff --git a/usr.sbin/lpr/lpq/Makefile b/usr.sbin/lpr/lpq/Makefile new file mode 100644 index 0000000..1c730c1 --- /dev/null +++ b/usr.sbin/lpr/lpq/Makefile @@ -0,0 +1,12 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= lpq +CFLAGS+=-I${.CURDIR}/../common_source +SRCS= lpq.c displayq.c common.c +BINOWN= root +BINGRP= daemon +BINMODE=6555 +BINDIR= /usr/bin +.PATH: ${.CURDIR}/../common_source + +.include diff --git a/usr.sbin/lpr/lpq/lpq.1 b/usr.sbin/lpr/lpq/lpq.1 new file mode 100644 index 0000000..50e1474 --- /dev/null +++ b/usr.sbin/lpr/lpq/lpq.1 @@ -0,0 +1,134 @@ +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)lpq.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt LPQ 1 +.Os BSD 4.2 +.Sh NAME +.Nm lpq +.Nd spool queue examination program +.Sh SYNOPSIS +.Nm lpq +.Op Fl l +.Op Fl P Ns Ar printer +.Op job # ... +.Op user ... +.Sh DESCRIPTION +.Nm Lpq +examines the spooling area used by +.Xr lpd 8 +for printing files on the line printer, and reports the status of the +specified jobs or all jobs associated with a user. +.Nm Lpq +invoked +without any arguments reports on any jobs currently in the queue. +.Pp +Options: +.Pp +.Bl -tag -width indent +.It Fl P +Specify a particular printer, otherwise the default +line printer is used (or the value of the +.Ev PRINTER +variable in the +environment). All other arguments supplied are interpreted as user +names or job numbers to filter out only those jobs of interest. +.It Fl l +Information about each of the files comprising the job entry +is printed. +Normally, only as much information as will fit on one line is displayed. +.El +.Pp +For each job submitted (i.e. invocation of +.Xr lpr 1 ) +.Nm lpq +reports the user's name, current rank in the queue, the +names of files comprising the job, the job identifier (a number which +may be supplied to +.Xr lprm 1 +for removing a specific job), and the total size in bytes. +Job ordering is dependent on +the algorithm used to scan the spooling directory and is supposed +to be +.Tn FIFO +(First in First Out). +File names comprising a job may be unavailable +(when +.Xr lpr 1 +is used as a sink in a pipeline) in which case the file +is indicated as ``(standard input)''. +.Pp +If +.Nm lpq +warns that there is no daemon present (i.e. due to some malfunction), +the +.Xr lpc 8 +command can be used to restart the printer daemon. +.Sh ENVIRONMENT +If the following environment variable exists, it is used by +.Nm lpq : +.Bl -tag -width PRINTER +.It Ev PRINTER +Specifies an alternate default printer. +.El +.Sh FILES +.Bl -tag -width /usr/share/misc/termcap -compact +.It Pa /etc/printcap +To determine printer characteristics. +.It Pa /var/spool/* +The spooling directory, as determined from printcap. +.It Pa /var/spool/*/cf* +Control files specifying jobs. +.It Pa /var/spool/*/lock +The lock file to obtain the currently active job. +.It Pa /usr/share/misc/termcap +For manipulating the screen for repeated display. +.El +.Sh SEE ALSO +.Xr lpr 1 , +.Xr lprm 1 , +.Xr lpc 8 , +.Xr lpd 8 +.Sh HISTORY +.Nm Lpq +appeared in +.Bx 3 . +.Sh BUGS +Due to the dynamic nature of the information in the spooling directory +.Nm lpq +may report unreliably. +Output formatting is sensitive to the line length of the terminal; +this can results in widely spaced columns. +.Sh DIAGNOSTICS +Unable to open various files. The lock file being malformed. Garbage +files when there is no daemon active, but files in the spooling directory. diff --git a/usr.sbin/lpr/lpq/lpq.c b/usr.sbin/lpr/lpq/lpq.c new file mode 100644 index 0000000..b091e8e --- /dev/null +++ b/usr.sbin/lpr/lpq/lpq.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)lpq.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * Spool Queue examination program + * + * lpq [-l] [-Pprinter] [user...] [job...] + * + * -l long output + * -P used to identify printer as per lpr/lprm + */ + +#include + +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "lp.local.h" + +int requ[MAXREQUESTS]; /* job number of spool entries */ +int requests; /* # of spool requests */ +char *user[MAXUSERS]; /* users to process */ +int users; /* # of users in user array */ + +void usage __P((void)); + +int +main(argc, argv) + register int argc; + register char **argv; +{ + extern char *optarg; + extern int optind; + int ch, lflag; /* long output option */ + + name = *argv; + if (gethostname(host, sizeof(host))) { + perror("lpq: gethostname"); + exit(1); + } + openlog("lpd", 0, LOG_LPR); + + lflag = 0; + while ((ch = getopt(argc, argv, "lP:")) != EOF) + switch((char)ch) { + case 'l': /* long output */ + ++lflag; + break; + case 'P': /* printer name */ + printer = optarg; + break; + case '?': + default: + usage(); + } + + if (printer == NULL && (printer = getenv("PRINTER")) == NULL) + printer = DEFLP; + + for (argc -= optind, argv += optind; argc; --argc, ++argv) + if (isdigit(argv[0][0])) { + if (requests >= MAXREQUESTS) + fatal("too many requests"); + requ[requests++] = atoi(*argv); + } + else { + if (users >= MAXUSERS) + fatal("too many users"); + user[users++] = *argv; + } + + displayq(lflag); + exit(0); +} + +void +usage() +{ + puts("usage: lpq [-l] [-Pprinter] [user ...] [job ...]"); + exit(1); +} diff --git a/usr.sbin/lpr/lpr/Makefile b/usr.sbin/lpr/lpr/Makefile new file mode 100644 index 0000000..9a3cbfd --- /dev/null +++ b/usr.sbin/lpr/lpr/Makefile @@ -0,0 +1,12 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= lpr +CFLAGS+=-I${.CURDIR}/../common_source +SRCS= lpr.c startdaemon.c common.c +BINOWN= root +BINGRP= daemon +BINMODE=6555 +BINDIR= /usr/bin +.PATH: ${.CURDIR}/../common_source + +.include diff --git a/usr.sbin/lpr/lpr/lpr.1 b/usr.sbin/lpr/lpr/lpr.1 new file mode 100644 index 0000000..382d508 --- /dev/null +++ b/usr.sbin/lpr/lpr/lpr.1 @@ -0,0 +1,256 @@ +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)lpr.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt LPR 1 +.Os BSD 4 +.Sh NAME +.Nm lpr +.Nd off line print +.Sh SYNOPSIS +.Nm lpr +.Op Fl P Ns Ar printer +.Op Fl \&# Ns Ar num +.Op Fl C Ar class +.Op Fl J Ar job +.Op Fl T Ar title +.Op Fl U Ar user +.Op Fl i Op Ar numcols +.Op Fl 1234 Ar font +.Op Fl w Ns Ar num +.Op Fl cdfghlnmprstv +.Op Ar name ... +.Sh DESCRIPTION +.Nm Lpr +uses a spooling daemon to print the named files when facilities +become available. If no names appear, the standard input is assumed. +.Pp +The following single letter options are used to notify the line printer +spooler that the files are not standard text files. The spooling daemon will +use the appropriate filters to print the data accordingly. +.Bl -tag -width indent +.It Fl c +The files are assumed to contain data produced by +.Xr cifplot 1 +.It Fl d +The files are assumed to contain data from +.Em tex +.Pf ( Tn DVI +format from Stanford). +.It Fl f +Use a filter which interprets the first character of each line as a +standard +.Tn FORTRAN +carriage control character. +.It Fl g +The files are assumed to contain standard plot data as produced by the +.Xr plot +routines (see also +.Xr plot +for the filters used by the printer spooler). +.It Fl l +Use a filter which allows control characters to be printed and suppresses +page breaks. +.It Fl n +The files are assumed to contain data from +.Em ditroff +(device independent troff). +.It Fl p +Use +.Xr pr 1 +to format the files (equivalent to +.Xr print ) . +.It Fl t +The files are assumed to contain data from +.Xr troff 1 +(cat phototypesetter commands). +.It Fl v +The files are assumed to contain a raster image for devices like the +Benson Varian. +.El +.Pp +These options apply to the handling of +the print job: +.Bl -tag -width indent +.It Fl P +Force output to a specific printer. Normally, +the default printer is used (site dependent), or the value of the +environment variable +.Ev PRINTER +is used. +.It Fl h +Suppress the printing of the burst page. +.It Fl m +Send mail upon completion. +.It Fl r +Remove the file upon completion of spooling or upon completion of +printing (with the +.Fl s +option). +.It Fl s +Use symbolic links. Usually files are copied to the spool directory. +The +.Fl s +option will use +.Xr symlink 2 +to link data files rather than trying to copy them so large files can be +printed. This means the files should +not be modified or removed until they have been printed. +.El +.Pp +The remaining options apply to copies, the page display, and headers: +.Bl -tag -width indent +.It Fl \&# Ns Ar num +The quantity +.Ar num +is the number of copies desired of each file named. For example, +.Bd -literal -offset indent +lpr \-#3 foo.c bar.c more.c +.Ed +would result in 3 copies of the file foo.c, followed by 3 copies +of the file bar.c, etc. On the other hand, +.Bd -literal -offset indent +cat foo.c bar.c more.c \&| lpr \-#3 +.Ed +.Pp +will give three copies of the concatenation of the files. Often +a site will disable this feature to encourage use of a photocopier +instead. +.It Xo +.Fl Ns Oo Cm 1234 Oc Ar font +.Xc +Specifies a +.Ar font +to be mounted on font position +.Ar i . +The daemon +will construct a +.Li .railmag +file referencing +the font pathname. +.It Fl C Ar class +Job classification +to use on the burst page. For example, +.Bd -literal -offset indent +lpr \-C EECS foo.c +.Ed +.Pp +causes the system name (the name returned by +.Xr hostname 1 ) +to be replaced on the burst page by +.Tn EECS , +and the file foo.c to be printed. +.It Fl J Ar job +Job name to print on the burst page. +Normally, the first file's name is used. +.It Fl T Ar title +Title name for +.Xr pr 1 , +instead of the file name. +.It Fl U Ar user +User name to print on the burst page, +also for accounting purposes. +This option is only honored if the real user-id is daemon +(or that specified in the printcap file instead of daemon), +and is intended for those instances where print filters wish to requeue jobs. +.It Fl i Op numcols +The output is indented. If the next argument +is numeric +.Pq Ar numcols , +it is used as the number of blanks to be printed before each +line; otherwise, 8 characters are printed. +.It Fl w Ns Ar num +Uses +.Ar num +as the page width for +.Xr pr 1 . +.El +.Sh ENVIRONMENT +If the following environment variable exists, it is used by +.Nm lpr : +.Bl -tag -width PRINTER +.It Ev PRINTER +Specifies an alternate default printer. +.El +.Sh FILES +.Bl -tag -width /var/spool/output/*/tf* -compact +.It Pa /etc/passwd +Personal identification. +.It Pa /etc/printcap +Printer capabilities data base. +.It Pa /usr/sbin/lpd* +Line printer daemons. +.It Pa /var/spool/output/* +Directories used for spooling. +.It Pa /var/spool/output/*/cf* +Daemon control files. +.It Pa /var/spool/output/*/df* +Data files specified in "cf" files. +.It Pa /var/spool/output/*/tf* +Temporary copies of "cf" files. +.El +.Sh SEE ALSO +.Xr lpq 1 , +.Xr lprm 1 , +.Xr pr 1 , +.Xr symlink 2 , +.Xr printcap 5 , +.Xr lpc 8 , +.Xr lpd 8 +.Sh HISTORY +The +.Nm lpr +command appeared in +.Bx 3 . +.Sh DIAGNOSTICS +If you try to spool too large a file, it will be truncated. +.Nm Lpr +will object to printing binary files. +If a user other than root prints a file and spooling is disabled, +.Nm lpr +will print a message saying so and will not put jobs in the queue. +If a connection to +.Xr lpd 1 +on the local machine cannot be made, +.Nm lpr +will say that the daemon cannot be started. +Diagnostics may be printed in the daemon's log file +regarding missing spool files by +.Xr lpd 1 . +.Sh BUGS +Fonts for +.Xr troff 1 +and +.Xr tex +reside on the host with the printer. It is currently not possible to +use local font libraries. diff --git a/usr.sbin/lpr/lpr/lpr.c b/usr.sbin/lpr/lpr/lpr.c new file mode 100644 index 0000000..8e9c45f --- /dev/null +++ b/usr.sbin/lpr/lpr/lpr.c @@ -0,0 +1,744 @@ +/* + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)lpr.c 8.3 (Berkeley) 3/30/94"; +#endif /* not lint */ + +/* + * lpr -- off line print + * + * Allows multiple printers and printers on remote machines by + * using information from a printer data base. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "lp.local.h" +#include "pathnames.h" + +static char *cfname; /* daemon control files, linked from tf's */ +static char *class = host; /* class title on header page */ +static char *dfname; /* data files */ +static char *fonts[4]; /* troff font names */ +static char format = 'f'; /* format char for printing files */ +static int hdr = 1; /* print header or not (default is yes) */ +static int iflag; /* indentation wanted */ +static int inchar; /* location to increment char in file names */ +static int indent; /* amount to indent */ +static char *jobname; /* job name on header page */ +static int mailflg; /* send mail */ +static int nact; /* number of jobs to act on */ +static int ncopies = 1; /* # of copies to make */ +static char *person; /* user name */ +static int qflag; /* q job, but don't exec daemon */ +static int rflag; /* remove files upon completion */ +static int sflag; /* symbolic link flag */ +static int tfd; /* control file descriptor */ +static char *tfname; /* tmp copy of cf before linking */ +static char *title; /* pr'ing title */ +static int userid; /* user id */ +static char *width; /* width for versatec printing */ + +static struct stat statb; + +static void card __P((int, char *)); +static void chkprinter __P((char *)); +static void cleanup __P((int)); +static void copy __P((int, char [])); +static void fatal2 __P((const char *, ...)); +static char *itoa __P((int)); +static char *linked __P((char *)); +static char *lmktemp __P((char *, int, int)); +static void mktemps __P((void)); +static int nfile __P((char *)); +static int test __P((char *)); + +void +main(argc, argv) + int argc; + char *argv[]; +{ + struct passwd *pw; + struct group *gptr; + extern char *itoa(); + register char *arg, *cp; + char buf[BUFSIZ]; + int i, f; + struct stat stb; + + if (signal(SIGHUP, SIG_IGN) != SIG_IGN) + signal(SIGHUP, cleanup); + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + signal(SIGINT, cleanup); + if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) + signal(SIGQUIT, cleanup); + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) + signal(SIGTERM, cleanup); + + name = argv[0]; + gethostname(host, sizeof (host)); + openlog("lpd", 0, LOG_LPR); + + while (argc > 1 && argv[1][0] == '-') { + argc--; + arg = *++argv; + switch (arg[1]) { + + case 'P': /* specifiy printer name */ + if (arg[2]) + printer = &arg[2]; + else if (argc > 1) { + argc--; + printer = *++argv; + } + break; + + case 'C': /* classification spec */ + hdr++; + if (arg[2]) + class = &arg[2]; + else if (argc > 1) { + argc--; + class = *++argv; + } + break; + + case 'U': /* user name */ + hdr++; + if (arg[2]) + person = &arg[2]; + else if (argc > 1) { + argc--; + person = *++argv; + } + break; + + case 'J': /* job name */ + hdr++; + if (arg[2]) + jobname = &arg[2]; + else if (argc > 1) { + argc--; + jobname = *++argv; + } + break; + + case 'T': /* pr's title line */ + if (arg[2]) + title = &arg[2]; + else if (argc > 1) { + argc--; + title = *++argv; + } + break; + + case 'l': /* literal output */ + case 'p': /* print using ``pr'' */ + case 't': /* print troff output (cat files) */ + case 'n': /* print ditroff output */ + case 'd': /* print tex output (dvi files) */ + case 'g': /* print graph(1G) output */ + case 'c': /* print cifplot output */ + case 'v': /* print vplot output */ + format = arg[1]; + break; + + case 'f': /* print fortran output */ + format = 'r'; + break; + + case '4': /* troff fonts */ + case '3': + case '2': + case '1': + if (argc > 1) { + argc--; + fonts[arg[1] - '1'] = *++argv; + } + break; + + case 'w': /* versatec page width */ + width = arg+2; + break; + + case 'r': /* remove file when done */ + rflag++; + break; + + case 'm': /* send mail when done */ + mailflg++; + break; + + case 'h': /* toggle want of header page */ + hdr = !hdr; + break; + + case 's': /* try to link files */ + sflag++; + break; + + case 'q': /* just q job */ + qflag++; + break; + + case 'i': /* indent output */ + iflag++; + indent = arg[2] ? atoi(&arg[2]) : 8; + break; + + case '#': /* n copies */ + if (isdigit(arg[2])) { + i = atoi(&arg[2]); + if (i > 0) + ncopies = i; + } + } + } + if (printer == NULL && (printer = getenv("PRINTER")) == NULL) + printer = DEFLP; + chkprinter(printer); + if (SC && ncopies > 1) + fatal2("multiple copies are not allowed"); + if (MC > 0 && ncopies > MC) + fatal2("only %d copies are allowed", MC); + /* + * Get the identity of the person doing the lpr using the same + * algorithm as lprm. + */ + userid = getuid(); + if (userid != DU || person == 0) { + if ((pw = getpwuid(userid)) == NULL) + fatal2("Who are you?"); + person = pw->pw_name; + } + /* + * Check for restricted group access. + */ + if (RG != NULL && userid != DU) { + if ((gptr = getgrnam(RG)) == NULL) + fatal2("Restricted group specified incorrectly"); + if (gptr->gr_gid != getgid()) { + while (*gptr->gr_mem != NULL) { + if ((strcmp(person, *gptr->gr_mem)) == 0) + break; + gptr->gr_mem++; + } + if (*gptr->gr_mem == NULL) + fatal2("Not a member of the restricted group"); + } + } + /* + * Check to make sure queuing is enabled if userid is not root. + */ + (void) sprintf(buf, "%s/%s", SD, LO); + if (userid && stat(buf, &stb) == 0 && (stb.st_mode & 010)) + fatal2("Printer queue is disabled"); + /* + * Initialize the control file. + */ + mktemps(); + tfd = nfile(tfname); + (void) fchown(tfd, DU, -1); /* owned by daemon for protection */ + card('H', host); + card('P', person); + if (hdr) { + if (jobname == NULL) { + if (argc == 1) + jobname = "stdin"; + else + jobname = (arg = rindex(argv[1], '/')) ? arg+1 : argv[1]; + } + card('J', jobname); + card('C', class); + card('L', person); + } + if (iflag) + card('I', itoa(indent)); + if (mailflg) + card('M', person); + if (format == 't' || format == 'n' || format == 'd') + for (i = 0; i < 4; i++) + if (fonts[i] != NULL) + card('1'+i, fonts[i]); + if (width != NULL) + card('W', width); + + /* + * Read the files and spool them. + */ + if (argc == 1) + copy(0, " "); + else while (--argc) { + if ((f = test(arg = *++argv)) < 0) + continue; /* file unreasonable */ + + if (sflag && (cp = linked(arg)) != NULL) { + (void) sprintf(buf, "%d %d", statb.st_dev, statb.st_ino); + card('S', buf); + if (format == 'p') + card('T', title ? title : arg); + for (i = 0; i < ncopies; i++) + card(format, &dfname[inchar-2]); + card('U', &dfname[inchar-2]); + if (f) + card('U', cp); + card('N', arg); + dfname[inchar]++; + nact++; + continue; + } + if (sflag) + printf("%s: %s: not linked, copying instead\n", name, arg); + if ((i = open(arg, O_RDONLY)) < 0) { + printf("%s: cannot open %s\n", name, arg); + continue; + } + copy(i, arg); + (void) close(i); + if (f && unlink(arg) < 0) + printf("%s: %s: not removed\n", name, arg); + } + + if (nact) { + (void) close(tfd); + tfname[inchar]--; + /* + * Touch the control file to fix position in the queue. + */ + if ((tfd = open(tfname, O_RDWR)) >= 0) { + char c; + + if (read(tfd, &c, 1) == 1 && + lseek(tfd, (off_t)0, 0) == 0 && + write(tfd, &c, 1) != 1) { + printf("%s: cannot touch %s\n", name, tfname); + tfname[inchar]++; + cleanup(0); + } + (void) close(tfd); + } + if (link(tfname, cfname) < 0) { + printf("%s: cannot rename %s\n", name, cfname); + tfname[inchar]++; + cleanup(0); + } + unlink(tfname); + if (qflag) /* just q things up */ + exit(0); + if (!startdaemon(printer)) + printf("jobs queued, but cannot start daemon.\n"); + exit(0); + } + cleanup(0); + /* NOTREACHED */ +} + +/* + * Create the file n and copy from file descriptor f. + */ +static void +copy(f, n) + int f; + char n[]; +{ + register int fd, i, nr, nc; + char buf[BUFSIZ]; + + if (format == 'p') + card('T', title ? title : n); + for (i = 0; i < ncopies; i++) + card(format, &dfname[inchar-2]); + card('U', &dfname[inchar-2]); + card('N', n); + fd = nfile(dfname); + nr = nc = 0; + while ((i = read(f, buf, BUFSIZ)) > 0) { + if (write(fd, buf, i) != i) { + printf("%s: %s: temp file write error\n", name, n); + break; + } + nc += i; + if (nc >= BUFSIZ) { + nc -= BUFSIZ; + nr++; + if (MX > 0 && nr > MX) { + printf("%s: %s: copy file is too large\n", name, n); + break; + } + } + } + (void) close(fd); + if (nc==0 && nr==0) + printf("%s: %s: empty input file\n", name, f ? n : "stdin"); + else + nact++; +} + +/* + * Try and link the file to dfname. Return a pointer to the full + * path name if successful. + */ +static char * +linked(file) + register char *file; +{ + register char *cp; + static char buf[BUFSIZ]; + + if (*file != '/') { + if (getwd(buf) == NULL) + return(NULL); + while (file[0] == '.') { + switch (file[1]) { + case '/': + file += 2; + continue; + case '.': + if (file[2] == '/') { + if ((cp = rindex(buf, '/')) != NULL) + *cp = '\0'; + file += 3; + continue; + } + } + break; + } + strcat(buf, "/"); + strcat(buf, file); + file = buf; + } + return(symlink(file, dfname) ? NULL : file); +} + +/* + * Put a line into the control file. + */ +static void +card(c, p2) + register int c; + register char *p2; +{ + char buf[BUFSIZ]; + register char *p1 = buf; + register int len = 2; + + *p1++ = c; + while ((c = *p2++) != '\0') { + *p1++ = (c == '\n') ? ' ' : c; + len++; + } + *p1++ = '\n'; + write(tfd, buf, len); +} + +/* + * Create a new file in the spool directory. + */ +static int +nfile(n) + char *n; +{ + register int f; + int oldumask = umask(0); /* should block signals */ + + f = open(n, O_WRONLY | O_EXCL | O_CREAT, FILMOD); + (void) umask(oldumask); + if (f < 0) { + printf("%s: cannot create %s\n", name, n); + cleanup(0); + } + if (fchown(f, userid, -1) < 0) { + printf("%s: cannot chown %s\n", name, n); + cleanup(0); + } + if (++n[inchar] > 'z') { + if (++n[inchar-2] == 't') { + printf("too many files - break up the job\n"); + cleanup(0); + } + n[inchar] = 'A'; + } else if (n[inchar] == '[') + n[inchar] = 'a'; + return(f); +} + +/* + * Cleanup after interrupts and errors. + */ +static void +cleanup(signo) + int signo; +{ + register i; + + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + i = inchar; + if (tfname) + do + unlink(tfname); + while (tfname[i]-- != 'A'); + if (cfname) + do + unlink(cfname); + while (cfname[i]-- != 'A'); + if (dfname) + do { + do + unlink(dfname); + while (dfname[i]-- != 'A'); + dfname[i] = 'z'; + } while (dfname[i-2]-- != 'd'); + exit(1); +} + +/* + * Test to see if this is a printable file. + * Return -1 if it is not, 0 if its printable, and 1 if + * we should remove it after printing. + */ +static int +test(file) + char *file; +{ + struct exec execb; + register int fd; + register char *cp; + + if (access(file, 4) < 0) { + printf("%s: cannot access %s\n", name, file); + return(-1); + } + if (stat(file, &statb) < 0) { + printf("%s: cannot stat %s\n", name, file); + return(-1); + } + if ((statb.st_mode & S_IFMT) == S_IFDIR) { + printf("%s: %s is a directory\n", name, file); + return(-1); + } + if (statb.st_size == 0) { + printf("%s: %s is an empty file\n", name, file); + return(-1); + } + if ((fd = open(file, O_RDONLY)) < 0) { + printf("%s: cannot open %s\n", name, file); + return(-1); + } + if (read(fd, &execb, sizeof(execb)) == sizeof(execb) && + !N_BADMAG(execb)) { + printf("%s: %s is an executable program", name, file); + goto error1; + } + (void) close(fd); + if (rflag) { + if ((cp = rindex(file, '/')) == NULL) { + if (access(".", 2) == 0) + return(1); + } else { + if (cp == file) { + fd = access("/", 2); + } else { + *cp = '\0'; + fd = access(file, 2); + *cp = '/'; + } + if (fd == 0) + return(1); + } + printf("%s: %s: is not removable by you\n", name, file); + } + return(0); + +error1: + printf(" and is unprintable\n"); + (void) close(fd); + return(-1); +} + +/* + * itoa - integer to string conversion + */ +static char * +itoa(i) + register int i; +{ + static char b[10] = "########"; + register char *p; + + p = &b[8]; + do + *p-- = i%10 + '0'; + while (i /= 10); + return(++p); +} + +/* + * Perform lookup for printer name or abbreviation -- + */ +static void +chkprinter(s) + char *s; +{ + int status; + + if ((status = cgetent(&bp, printcapdb, s)) == -2) + fatal2("cannot open printer description file"); + else if (status == -1) + fatal2("%s: unknown printer", s); + if (cgetstr(bp, "sd", &SD) == -1) + SD = _PATH_DEFSPOOL; + if (cgetstr(bp, "lo", &LO) == -1) + LO = DEFLOCK; + cgetstr(bp, "rg", &RG); + if (cgetnum(bp, "mx", &MX) < 0) + MX = DEFMX; + if (cgetnum(bp,"mc", &MC) < 0) + MC = DEFMAXCOPIES; + if (cgetnum(bp, "du", &DU) < 0) + DU = DEFUID; + SC = (cgetcap(bp, "sc", ':') != NULL); +} + +/* + * Make the temp files. + */ +static void +mktemps() +{ + register int len, fd, n; + register char *cp; + char buf[BUFSIZ]; + char *lmktemp(); + + (void) sprintf(buf, "%s/.seq", SD); + if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) { + printf("%s: cannot create %s\n", name, buf); + exit(1); + } + if (flock(fd, LOCK_EX)) { + printf("%s: cannot lock %s\n", name, buf); + exit(1); + } + n = 0; + if ((len = read(fd, buf, sizeof(buf))) > 0) { + for (cp = buf; len--; ) { + if (*cp < '0' || *cp > '9') + break; + n = n * 10 + (*cp++ - '0'); + } + } + len = strlen(SD) + strlen(host) + 8; + tfname = lmktemp("tf", n, len); + cfname = lmktemp("cf", n, len); + dfname = lmktemp("df", n, len); + inchar = strlen(SD) + 3; + n = (n + 1) % 1000; + (void) lseek(fd, (off_t)0, 0); + sprintf(buf, "%03d\n", n); + (void) write(fd, buf, strlen(buf)); + (void) close(fd); /* unlocks as well */ +} + +/* + * Make a temp file name. + */ +static char * +lmktemp(id, num, len) + char *id; + int num, len; +{ + register char *s; + + if ((s = malloc(len)) == NULL) + fatal2("out of memory"); + (void) sprintf(s, "%s/%sA%03d%s", SD, id, num, host); + return(s); +} + +#if __STDC__ +#include +#else +#include +#endif + +static void +#if __STDC__ +fatal2(const char *msg, ...) +#else +fatal2(msg, va_alist) + char *msg; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, msg); +#else + va_start(ap); +#endif + printf("%s: ", name); + vprintf(msg, ap); + putchar('\n'); + va_end(ap); + exit(1); +} diff --git a/usr.sbin/lpr/lprm/Makefile b/usr.sbin/lpr/lprm/Makefile new file mode 100644 index 0000000..d1362f5 --- /dev/null +++ b/usr.sbin/lpr/lprm/Makefile @@ -0,0 +1,12 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= lprm +CFLAGS+=-I${.CURDIR}/../common_source +SRCS= lprm.c rmjob.c startdaemon.c common.c +BINOWN= root +BINGRP= daemon +BINMODE=6555 +BINDIR= /usr/bin +.PATH: ${.CURDIR}/../common_source + +.include diff --git a/usr.sbin/lpr/lprm/lprm.1 b/usr.sbin/lpr/lprm/lprm.1 new file mode 100644 index 0000000..22309d1 --- /dev/null +++ b/usr.sbin/lpr/lprm/lprm.1 @@ -0,0 +1,145 @@ +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)lprm.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt LPRM 1 +.Os BSD 4.2 +.Sh NAME +.Nm lprm +.Nd remove jobs from the line printer spooling queue +.Sh SYNOPSIS +.Nm lprm +.Op Fl P Ns Ar printer +.Op Fl +.Op job # ... +.Op Ar user ... +.Sh DESCRIPTION +.Nm Lprm +will remove a job, or jobs, from a printer's spool queue. +Since the spooling directory is protected from users, using +.Nm lprm +is normally the only method by which a user may remove a job. +The owner of a job is determined by the user's login name +and host name on the machine where the +.Xr lpr 1 +command was invoked. +.Pp +Options and arguments: +.Bl -tag -width indent +.It Fl P Ns Ar printer +Specify the queue associated with a specific +.Ar printer +(otherwise the default printer is used). +.It Fl +If a single +.Sq Fl +is given, +.Nm lprm +will remove all jobs which a user +owns. If the super-user employs this flag, the spool queue will +be emptied entirely. +.It Ar user +Causes +.Nm lprm +to attempt to remove any jobs queued belonging to that user +(or users). This form of invoking +.Nm lprm +is useful only to the super-user. +.It Ar job\ \&# +A user may dequeue an individual job by specifying its job number. +This number may be obtained from the +.Xr lpq 1 +program, e.g. +.Pp +.Bd -literal -offset indent +\&% lpq \-l + +1st:ken [job #013ucbarpa] + (standard input) 100 bytes +% lprm 13 +.Ed +.El +.Pp +If neither arguments or options are given, +.Nm Lprm +will delete the currently active job if it is +owned by the user who invoked +.Nm lprm . +.Pp +.Nm Lprm +announces the names of any files it removes and is silent if +there are no jobs in the queue which match the request list. +.Pp +.Nm Lprm +will kill off an active daemon, if necessary, before removing +any spooling files. If a daemon is killed, a new one is +automatically restarted upon completion of file removals. +.Sh ENVIRONMENT +If the following environment variable exists, it is utilized by +.Nm lprm . +.Bl -tag -width PRINTER +.It Ev PRINTER +If the environment variable +.Ev PRINTER +exists, +and a printer has not been specified with the +.Fl P +option, +the default printer is assumed from +.Ev PRINTER . +.El +.Sh FILES +.Bl -tag -width /var/spool/*/lock/ -compact +.It Pa /etc/printcap +Printer characteristics file. +.It Pa /var/spool/* +Spooling directories. +.It Pa /var/spool/*/lock +Lock file used to obtain the pid of the current +daemon and the job number of the currently active job. +.El +.Sh SEE ALSO +.Xr lpr 1 , +.Xr lpq 1 , +.Xr lpd 8 +.Sh DIAGNOSTICS +``Permission denied" if the user tries to remove files other than his +own. +.Sh BUGS +Since there are race conditions possible in the update of the lock file, +the currently active job may be incorrectly identified. +.Sh HISTORY +The +.Nm lprm +command appeared in +.Bx 3.0 . diff --git a/usr.sbin/lpr/lprm/lprm.c b/usr.sbin/lpr/lprm/lprm.c new file mode 100644 index 0000000..20c4ee7 --- /dev/null +++ b/usr.sbin/lpr/lprm/lprm.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)lprm.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * lprm - remove the current user's spool entry + * + * lprm [-] [[job #] [user] ...] + * + * Using information in the lock file, lprm will kill the + * currently active daemon (if necessary), remove the associated files, + * and startup a new daemon. Priviledged users may remove anyone's spool + * entries, otherwise one can only remove their own. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "lp.h" +#include "lp.local.h" + +/* + * Stuff for handling job specifications + */ +char *person; /* name of person doing lprm */ +int requ[MAXREQUESTS]; /* job number of spool entries */ +int requests; /* # of spool requests */ +char *user[MAXUSERS]; /* users to process */ +int users; /* # of users in user array */ + +static char luser[16]; /* buffer for person */ + +void usage __P((void)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + register char *arg; + struct passwd *p; + + name = argv[0]; + gethostname(host, sizeof(host)); + openlog("lpd", 0, LOG_LPR); + if ((p = getpwuid(getuid())) == NULL) + fatal("Who are you?"); + if (strlen(p->pw_name) >= sizeof(luser)) + fatal("Your name is too long"); + strcpy(luser, p->pw_name); + person = luser; + while (--argc) { + if ((arg = *++argv)[0] == '-') + switch (arg[1]) { + case 'P': + if (arg[2]) + printer = &arg[2]; + else if (argc > 1) { + argc--; + printer = *++argv; + } + break; + case '\0': + if (!users) { + users = -1; + break; + } + default: + usage(); + } + else { + if (users < 0) + usage(); + if (isdigit(arg[0])) { + if (requests >= MAXREQUESTS) + fatal("Too many requests"); + requ[requests++] = atoi(arg); + } else { + if (users >= MAXUSERS) + fatal("Too many users"); + user[users++] = arg; + } + } + } + if (printer == NULL && (printer = getenv("PRINTER")) == NULL) + printer = DEFLP; + + rmjob(); + exit(0); +} + +void +usage() +{ + fprintf(stderr, "usage: lprm [-] [-Pprinter] [[job #] [user] ...]\n"); + exit(2); +} diff --git a/usr.sbin/lpr/lptest/Makefile b/usr.sbin/lpr/lptest/Makefile new file mode 100644 index 0000000..6ff8e7f --- /dev/null +++ b/usr.sbin/lpr/lptest/Makefile @@ -0,0 +1,6 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= lptest + +.include "../../Makefile.inc" +.include diff --git a/usr.sbin/lpr/lptest/lptest.1 b/usr.sbin/lpr/lptest/lptest.1 new file mode 100644 index 0000000..95b28f3 --- /dev/null +++ b/usr.sbin/lpr/lptest/lptest.1 @@ -0,0 +1,74 @@ +.\" Copyright (c) 1985, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)lptest.1 8.2 (Berkeley) 12/30/93 +.\" +.Dd December 30, 1993 +.Dt LPTEST 1 +.Os BSD 4.3 +.Sh NAME +.Nm lptest +.Nd generate lineprinter ripple pattern +.Sh SYNOPSIS +.Nm lptest +.Op Ar length +.Op Ar count +.Sh DESCRIPTION +.Nm Lptest +writes the traditional "ripple test" pattern on standard output. +In 96 lines, +this pattern will print all 96 printable +.Tn ASCII +characters +in each position. +While originally created to test printers, it is quite +useful for testing terminals, +driving terminal ports for debugging purposes, +or any other task where a quick supply of random data is needed. +.Pp +The +.Ar length +argument specifies the output line length if the default +length of 79 is inappropriate. +.Pp +The +.Ar count +argument specifies the number of output lines to be generated if +the default count of 200 is inappropriate. +Note that if +.Ar count +is to be specified, +.Ar length +must be also be specified. +.Sh HISTORY +.Nm Lptest +appeared in +.Bx 4.3 . diff --git a/usr.sbin/lpr/lptest/lptest.c b/usr.sbin/lpr/lptest/lptest.c new file mode 100644 index 0000000..5ce80b5 --- /dev/null +++ b/usr.sbin/lpr/lptest/lptest.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)lptest.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include +#include + +/* + * lptest -- line printer test program (and other devices). + */ +void +main(argc, argv) + int argc; + char **argv; +{ + int len, count; + register i, j, fc, nc; + char outbuf[BUFSIZ]; + + setbuf(stdout, outbuf); + if (argc >= 2) + len = atoi(argv[1]); + else + len = 79; + if (argc >= 3) + count = atoi(argv[2]); + else + count = 200; + fc = ' '; + for (i = 0; i < count; i++) { + if (++fc == 0177) + fc = ' '; + nc = fc; + for (j = 0; j < len; j++) { + putchar(nc); + if (++nc == 0177) + nc = ' '; + } + putchar('\n'); + } + (void) fflush(stdout); + exit(0); +} diff --git a/usr.sbin/lpr/pac/Makefile b/usr.sbin/lpr/pac/Makefile new file mode 100644 index 0000000..70cea89 --- /dev/null +++ b/usr.sbin/lpr/pac/Makefile @@ -0,0 +1,10 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= pac +CFLAGS+=-I${.CURDIR}/../common_source +MAN8= pac.0 +SRCS= pac.c common.c +.PATH: ${.CURDIR}/../common_source + +.include "../../Makefile.inc" +.include diff --git a/usr.sbin/lpr/pac/pac.8 b/usr.sbin/lpr/pac/pac.8 new file mode 100644 index 0000000..6e7ffc0 --- /dev/null +++ b/usr.sbin/lpr/pac/pac.8 @@ -0,0 +1,106 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)pac.8 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt PAC 8 +.Os BSD 4.2 +.Sh NAME +.Nm pac +.Nd printer/plotter accounting information +.Sh SYNOPSIS +.Nm pac +.Op Fl P Ns Ar printer +.Op Fl c +.Op Fl m +.Op Fl p Ns Ar price +.Op Fl s +.Op Fl r +.Op Ar name ... +.Sh DESCRIPTION +.Nm Pac +reads the printer/plotter accounting files, accumulating the number +of pages (the usual case) or feet (for raster devices) +of paper consumed by each user, and printing out +how much each user consumed in pages or feet and dollars. +.Pp +Options and operands available: +.Bl -tag -width PPprinter +.It Fl P Ns Ar printer +Accounting is done for the named printer. +Normally, accounting is done for the default printer (site dependent) or +the value of the environment variable +.Ev PRINTER +is used. +.It Fl c +flag causes the output to be sorted by cost; usually the +output is sorted alphabetically by name. +.It Fl m +flag causes the host name to be ignored in the accounting file. This +allows for a user on multiple machines to have all of his printing +charges grouped together. +.It Fl p Ns Ar price +The value +.Ar price +is used for the cost in dollars instead of the default value of 0.02 +or the price specified in +.Pa /etc/printcap . +.It Fl r +Reverse the sorting order. +.It Fl s +Accounting information is summarized on the +summary accounting file; this summarization is necessary since on a +busy system, the accounting file can grow by several lines per day. +.It Ar names +Statistics are only printed for user(s) +.Ar name ; +usually, statistics are printed for every user who has used any paper. +.El +.Sh FILES +.Bl -tag -width /var/account/?_sum -compact +.It Pa /var/account/?acct +raw accounting files +.It Pa /var/account/?_sum +summary accounting files +.It Pa /etc/printcap +printer capability data base +.El +.Sh SEE ALSO +.Xr printcap 5 +.Sh BUGS +The relationship between the computed price and reality is +as yet unknown. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.0 . diff --git a/usr.sbin/lpr/pac/pac.c b/usr.sbin/lpr/pac/pac.c new file mode 100644 index 0000000..af0c8cc --- /dev/null +++ b/usr.sbin/lpr/pac/pac.c @@ -0,0 +1,444 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)pac.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * Do Printer accounting summary. + * Currently, usage is + * pac [-Pprinter] [-pprice] [-s] [-r] [-c] [-m] [user ...] + * to print the usage information for the named people. + */ + +#include + +#include +#include +#include +#include +#include "lp.h" +#include "lp.local.h" + +static char *acctfile; /* accounting file (input data) */ +static int allflag = 1; /* Get stats on everybody */ +static int errs; +static int hcount; /* Count of hash entries */ +static int mflag = 0; /* disregard machine names */ +static int pflag = 0; /* 1 if -p on cmd line */ +static float price = 0.02; /* cost per page (or what ever) */ +static long price100; /* per-page cost in 100th of a cent */ +static int reverse; /* Reverse sort order */ +static int sort; /* Sort by cost */ +static char *sumfile; /* summary file */ +static int summarize; /* Compress accounting file */ + +/* + * Grossness follows: + * Names to be accumulated are hashed into the following + * table. + */ + +#define HSHSIZE 97 /* Number of hash buckets */ + +struct hent { + struct hent *h_link; /* Forward hash link */ + char *h_name; /* Name of this user */ + float h_feetpages; /* Feet or pages of paper */ + int h_count; /* Number of runs */ +}; + +static struct hent *hashtab[HSHSIZE]; /* Hash table proper */ + +static void account __P((FILE *)); +static int any __P((int, char [])); +static int chkprinter __P((char *)); +static void dumpit __P((void)); +static int hash __P((char [])); +static struct hent *enter __P((char [])); +static struct hent *lookup __P((char [])); +static int qucmp __P((const void *, const void *)); +static void rewrite __P((void)); + +void +main(argc, argv) + int argc; + char **argv; +{ + register FILE *acct; + register char *cp; + + while (--argc) { + cp = *++argv; + if (*cp++ == '-') { + switch(*cp++) { + case 'P': + /* + * Printer name. + */ + printer = cp; + continue; + + case 'p': + /* + * get the price. + */ + price = atof(cp); + pflag = 1; + continue; + + case 's': + /* + * Summarize and compress accounting file. + */ + summarize++; + continue; + + case 'c': + /* + * Sort by cost. + */ + sort++; + continue; + + case 'm': + /* + * disregard machine names for each user + */ + mflag = 1; + continue; + + case 'r': + /* + * Reverse sorting order. + */ + reverse++; + continue; + + default: +fprintf(stderr, + "usage: pac [-Pprinter] [-pprice] [-s] [-c] [-r] [-m] [user ...]\n"); + exit(1); + } + } + (void) enter(--cp); + allflag = 0; + } + if (printer == NULL && (printer = getenv("PRINTER")) == NULL) + printer = DEFLP; + if (!chkprinter(printer)) { + printf("pac: unknown printer %s\n", printer); + exit(2); + } + + if ((acct = fopen(acctfile, "r")) == NULL) { + perror(acctfile); + exit(1); + } + account(acct); + fclose(acct); + if ((acct = fopen(sumfile, "r")) != NULL) { + account(acct); + fclose(acct); + } + if (summarize) + rewrite(); + else + dumpit(); + exit(errs); +} + +/* + * Read the entire accounting file, accumulating statistics + * for the users that we have in the hash table. If allflag + * is set, then just gather the facts on everyone. + * Note that we must accomodate both the active and summary file + * formats here. + * Host names are ignored if the -m flag is present. + */ +static void +account(acct) + register FILE *acct; +{ + char linebuf[BUFSIZ]; + double t; + register char *cp, *cp2; + register struct hent *hp; + register int ic; + + while (fgets(linebuf, BUFSIZ, acct) != NULL) { + cp = linebuf; + while (any(*cp, " t\t")) + cp++; + t = atof(cp); + while (any(*cp, ".0123456789")) + cp++; + while (any(*cp, " \t")) + cp++; + for (cp2 = cp; !any(*cp2, " \t\n"); cp2++) + ; + ic = atoi(cp2); + *cp2 = '\0'; + if (mflag && index(cp, ':')) + cp = index(cp, ':') + 1; + hp = lookup(cp); + if (hp == NULL) { + if (!allflag) + continue; + hp = enter(cp); + } + hp->h_feetpages += t; + if (ic) + hp->h_count += ic; + else + hp->h_count++; + } +} + +/* + * Sort the hashed entries by name or footage + * and print it all out. + */ +static void +dumpit() +{ + struct hent **base; + register struct hent *hp, **ap; + register int hno, c, runs; + float feet; + + hp = hashtab[0]; + hno = 1; + base = (struct hent **) calloc(sizeof hp, hcount); + for (ap = base, c = hcount; c--; ap++) { + while (hp == NULL) + hp = hashtab[hno++]; + *ap = hp; + hp = hp->h_link; + } + qsort(base, hcount, sizeof hp, qucmp); + printf(" Login pages/feet runs price\n"); + feet = 0.0; + runs = 0; + for (ap = base, c = hcount; c--; ap++) { + hp = *ap; + runs += hp->h_count; + feet += hp->h_feetpages; + printf("%-24s %7.2f %4d $%6.2f\n", hp->h_name, + hp->h_feetpages, hp->h_count, hp->h_feetpages * price); + } + if (allflag) { + printf("\n"); + printf("%-24s %7.2f %4d $%6.2f\n", "total", feet, + runs, feet * price); + } +} + +/* + * Rewrite the summary file with the summary information we have accumulated. + */ +static void +rewrite() +{ + register struct hent *hp; + register int i; + register FILE *acctf; + + if ((acctf = fopen(sumfile, "w")) == NULL) { + perror(sumfile); + errs++; + return; + } + for (i = 0; i < HSHSIZE; i++) { + hp = hashtab[i]; + while (hp != NULL) { + fprintf(acctf, "%7.2f\t%s\t%d\n", hp->h_feetpages, + hp->h_name, hp->h_count); + hp = hp->h_link; + } + } + fflush(acctf); + if (ferror(acctf)) { + perror(sumfile); + errs++; + } + fclose(acctf); + if ((acctf = fopen(acctfile, "w")) == NULL) + perror(acctfile); + else + fclose(acctf); +} + +/* + * Hashing routines. + */ + +/* + * Enter the name into the hash table and return the pointer allocated. + */ + +static struct hent * +enter(name) + char name[]; +{ + register struct hent *hp; + register int h; + + if ((hp = lookup(name)) != NULL) + return(hp); + h = hash(name); + hcount++; + hp = (struct hent *) calloc(sizeof *hp, 1); + hp->h_name = (char *) calloc(sizeof(char), strlen(name)+1); + strcpy(hp->h_name, name); + hp->h_feetpages = 0.0; + hp->h_count = 0; + hp->h_link = hashtab[h]; + hashtab[h] = hp; + return(hp); +} + +/* + * Lookup a name in the hash table and return a pointer + * to it. + */ + +static struct hent * +lookup(name) + char name[]; +{ + register int h; + register struct hent *hp; + + h = hash(name); + for (hp = hashtab[h]; hp != NULL; hp = hp->h_link) + if (strcmp(hp->h_name, name) == 0) + return(hp); + return(NULL); +} + +/* + * Hash the passed name and return the index in + * the hash table to begin the search. + */ +static int +hash(name) + char name[]; +{ + register int h; + register char *cp; + + for (cp = name, h = 0; *cp; h = (h << 2) + *cp++) + ; + return((h & 0x7fffffff) % HSHSIZE); +} + +/* + * Other stuff + */ +static int +any(ch, str) + int ch; + char str[]; +{ + register int c = ch; + register char *cp = str; + + while (*cp) + if (*cp++ == c) + return(1); + return(0); +} + +/* + * The qsort comparison routine. + * The comparison is ascii collating order + * or by feet of typesetter film, according to sort. + */ +static int +qucmp(a, b) + const void *a, *b; +{ + register struct hent *h1, *h2; + register int r; + + h1 = *(struct hent **)a; + h2 = *(struct hent **)b; + if (sort) + r = h1->h_feetpages < h2->h_feetpages ? + -1 : h1->h_feetpages > h2->h_feetpages; + else + r = strcmp(h1->h_name, h2->h_name); + return(reverse ? -r : r); +} + +/* + * Perform lookup for printer name or abbreviation -- + */ +static int +chkprinter(s) + register char *s; +{ + int stat; + + if ((stat = cgetent(&bp, printcapdb, s)) == -2) { + printf("pac: can't open printer description file\n"); + exit(3); + } else if (stat == -1) + return(0); + else if (stat == -3) + fatal("potential reference loop detected in printcap file"); + + if (cgetstr(bp, "af", &acctfile) == -1) { + printf("accounting not enabled for printer %s\n", printer); + exit(2); + } + if (!pflag && (cgetnum(bp, "pc", &price100) == 0)) + price = price100/10000.0; + sumfile = (char *) calloc(sizeof(char), strlen(acctfile)+5); + if (sumfile == NULL) { + perror("pac"); + exit(1); + } + strcpy(sumfile, acctfile); + strcat(sumfile, "_sum"); + return(1); +} -- cgit v1.1