lpr-2008.05.17.3+nmu1/0000755000000000000000000000000013416173536010627 5ustar lpr-2008.05.17.3+nmu1/Makefile0000644000000000000000000000037210176611664012270 0ustar SUBDIR= lpc lpd lpq lpr lprm lptest pac filters all: for dir in $(SUBDIR); do \ $(MAKE) -C $$dir; \ if [ 0 -ne $$? ] ; then return 2; fi; \ done clean: for dir in $(SUBDIR); do \ $(MAKE) -C $$dir clean;\ done cd common_source; rm -f *.o lpr-2008.05.17.3+nmu1/Makefile.in0000644000000000000000000000026510177467754012710 0ustar SRCS+= ../common_source/strlcpy.c ../common_source/strlcat.c OBJ=${SRCS:.c=.o} .o.c: $(CC) ${CFLAGS} -c $< ${PROG}: ${OBJ} $(CC) -o ${PROG} ${OBJ} clean: rm -f *.o ${PROG} lpr-2008.05.17.3+nmu1/SMM.doc/0000755000000000000000000000000010176607330012021 5ustar lpr-2008.05.17.3+nmu1/SMM.doc/0.t0000644000000000000000000000452507666757625012402 0ustar .\" $OpenBSD: 0.t,v 1.4 2003/06/02 23:36:53 millert Exp $ .\" .\" 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. 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 OpenBSD Line Printer Spooler Manual .EH 'SMM:7-%''OpenBSD Line Printer Spooler Manual' .OH 'OpenBSD 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 This document describes the structure and installation procedure for the line printer spooling system included with the OpenBSD operating system. .de D? .ie \\n(.$>1 Revised \\$1 \\$2 \\$3 .el DRAFT of \n(mo/\n(dy/\n(yr .. .sp 2 .LP .D? May 31, 2002 .AE .de IR \fI\\$1\fP\\$2 .. .de DT .TA 8 16 24 32 40 48 56 64 72 80 .. lpr-2008.05.17.3+nmu1/SMM.doc/1.t0000644000000000000000000000577107666757625012407 0ustar .\" $OpenBSD: 1.t,v 1.4 2003/06/02 23:36:53 millert Exp $ .\" .\" 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. 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/sbin/lpd line printer daemon, does all the real work /usr/bin/lpr program to enter a job in a printer queue /usr/bin/lpq spooling queue examination program /usr/bin/lprm program to delete jobs from a queue /usr/sbin/lpc program to administer printers and spooling queues /var/run/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 . lpr-2008.05.17.3+nmu1/SMM.doc/2.t0000644000000000000000000001214107666757625012375 0ustar .\" $OpenBSD: 2.t,v 1.5 2003/06/02 23:36:53 millert Exp $ .\" .\" 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. 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 LOCAL domain (named ``/var/run/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\|(8) and \fIrcmd\fP\|(3). 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. lpr-2008.05.17.3+nmu1/SMM.doc/3.t0000644000000000000000000000577307666757625012413 0ustar .\" $OpenBSD: 3.t,v 1.5 2003/06/02 23:36:53 millert Exp $ .\" .\" 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. 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 \fIroot\fP and and the \fIdaemon\fP group. .IP \(bu 3 The \fIlpr\fP and \fIlprm\fP programs run set-user-id to user \fIdaemon\fP and set-group-id to group \fIdaemon\fP. .IP \(bu 3 The \fIlpc\fP and \fIlpq\fP programs run set-group-id to group \fIdaemon\fP to access spool files. .IP \(bu 3 Control and data files in a spooling area are made with \fIdaemon\fP ownership and group ownership \fIdaemon\fP. Their mode is 0660. This ensures control files are not modified by a user and that no user can remove files except through \fIlprm\fP. .IP \(bu 3 The printer server, \fIlpd\fP, runs as \fIroot\fP but spends most of its time with the effective user-id set to \fIdaemon\fP and the effective group-id set to \fIdaemon\fP. As a result, spool files it creates belong to user and group \fIdaemon\fP. \fILpd\fP uses the same verification procedures as \fIrshd\fP\|(8) 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. lpr-2008.05.17.3+nmu1/SMM.doc/4.t0000644000000000000000000001623707666757625012411 0ustar .\" $OpenBSD: 4.t,v 1.5 2003/06/02 23:36:53 millert Exp $ .\" .\" 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. 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 OpenBSD 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.sbin/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 9600 baud serial line. .DS .DT lp|LA-180 DecWriter III:\e :lp=/dev/lp:br#9600:ms=onlcr,oxtabs,-parity:\e :tr=\ef:of=/usr/libexec/lpr/lpf:lf=/var/log/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 ms entry sets NL to CR-NL mapping, expansion of tabs to spaces, and disables parity (see \fIstty\fP\|(1)). 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 ``/var/log/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=/var/spool/output/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 ``/var/spool/output/vaxlpd'' as the spooling directory instead of the default value of ``/var/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=/var/spool/output/vad:of=/usr/libexec/lpr/vpf:\e :tf=/usr/libexec/lpr/rvcat:mx#2000:pl#58:px=2112:py=1700:tr=\ef: .DE The .B tf entry specifies ``/usr/libexec/lpr/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\|(4)). 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=/var/spool/output/vad:of=/usr/libexec/lpr/vpf:\e :if=/usr/libexec/lpr/vpf:tf=/usr/libexec/lpr/rvcat:\e :af=/var/log/vaacct: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 lpr-2008.05.17.3+nmu1/SMM.doc/5.t0000644000000000000000000000763510176607055012371 0ustar .\" $OpenBSD: 5.t,v 1.5 2004/04/14 20:52:20 millert Exp $ .\" .\" 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. 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 OpenBSD 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\-j\fP jobname \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 . The .B \-j parameter is optional and specifies the name of the print job if available. .PP All other filters are called with the following arguments: .DS \fIfilter\fP \fB\-x\fPwidth \fB\-y\fPlength \fB\-n\fP login \fB\-j\fP jobname \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. lpr-2008.05.17.3+nmu1/SMM.doc/6.t0000644000000000000000000000772607666757625012416 0ustar .\" $OpenBSD: 6.t,v 1.4 2003/06/02 23:36:53 millert Exp $ .\" .\" 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. 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. .LP \fBup\fP and \fBdown\fP .IP \fIUp\fP and \fIdown\fP combine the functionality of \fIenable\fP and \fIstart\fP with \fIstart\fP and \fIstop\fP. \fIUp\fP is equivalent to issuing the \fIstart\fP and \fIenable\fP commands, whereas \fIdown\fP is equivalent to issuing the \fIstop\fP and \fIdisable\fP commands. \fIDown\fP also takes an optional message that will be written to the printer's status file. This allows the administrator to indicate to users why the printer is out of service. lpr-2008.05.17.3+nmu1/SMM.doc/7.t0000644000000000000000000001535407666757625012413 0ustar .\" $OpenBSD: 7.t,v 1.5 2003/06/02 23:36:53 millert Exp $ .\" .\" 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. 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 /var/run/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/sbin/lpd .DE You can also check the state of the master printer daemon with the following. .DS % ps l`cat /var/run/lpd.pid` .DE .IP Another possibility is that the .I lpr program is not set-user-id to \fIdaemon\fP, set-group-id to group \fIdaemon\fP. This can be checked with .DS % ls \-l /usr/bin/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. lpr-2008.05.17.3+nmu1/SMM.doc/Makefile0000644000000000000000000000047310176607055013471 0ustar # from: @(#)Makefile 8.1 (Berkeley) 6/8/93 # $OpenBSD: Makefile,v 1.3 2004/02/01 14:56:21 jmc Exp $ 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} paper.txt: ${SRCS} ${TBL} ${SRCS} | ${ROFF} -Tascii > ${.TARGET} .include lpr-2008.05.17.3+nmu1/SMM.doc/spell.ok0000644000000000000000000000064607500261647013505 0ustar 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 lpr-2008.05.17.3+nmu1/UPSTREAM_VERSIONS0000644000000000000000000000701411014363350013327 0ustar The upstream source of the changes to these files is OpenBSD CVS. When synching with OpenBSD, please add any relavent parts of the CVS logs to GIT log and modify the revision version in this file. The current versions of files used by lpr (core) are: revision: 1.4 /cvs/src/usr.sbin/lpr/Makefile revision: 1.4 /cvs/src/usr.sbin/lpr/SMM.doc/0.t revision: 1.4 /cvs/src/usr.sbin/lpr/SMM.doc/1.t revision: 1.5 /cvs/src/usr.sbin/lpr/SMM.doc/2.t revision: 1.5 /cvs/src/usr.sbin/lpr/SMM.doc/3.t revision: 1.5 /cvs/src/usr.sbin/lpr/SMM.doc/4.t revision: 1.5 /cvs/src/usr.sbin/lpr/SMM.doc/5.t revision: 1.4 /cvs/src/usr.sbin/lpr/SMM.doc/6.t revision: 1.5 /cvs/src/usr.sbin/lpr/SMM.doc/7.t revision: 1.3 /cvs/src/usr.sbin/lpr/SMM.doc/Makefile revision: 1.2 /cvs/src/usr.sbin/lpr/SMM.doc/spell.ok revision: 1.32 /cvs/src/usr.sbin/lpr/common_source/common.c revision: 1.3 /cvs/src/usr.sbin/lpr/common_source/common_vars.c revision: 1.29 /cvs/src/usr.sbin/lpr/common_source/displayq.c revision: 1.14 /cvs/src/usr.sbin/lpr/common_source/lp.h revision: 1.4 /cvs/src/usr.sbin/lpr/common_source/lp.local.h revision: 1.4 /cvs/src/usr.sbin/lpr/common_source/pathnames.h revision: 1.17 /cvs/src/usr.sbin/lpr/common_source/rmjob.c revision: 1.12 /cvs/src/usr.sbin/lpr/common_source/startdaemon.c revision: 1.2 /cvs/src/usr.sbin/lpr/filters/Makefile revision: 1.11 /cvs/src/usr.sbin/lpr/filters/lpf.c revision: 1.3 /cvs/src/usr.sbin/lpr/lpc/Makefile revision: 1.19 /cvs/src/usr.sbin/lpr/lpc/cmds.c revision: 1.5 /cvs/src/usr.sbin/lpr/lpc/cmdtab.c revision: 1.5 /cvs/src/usr.sbin/lpr/lpc/extern.h revision: 1.13 /cvs/src/usr.sbin/lpr/lpc/lpc.8 revision: 1.17 /cvs/src/usr.sbin/lpr/lpc/lpc.c revision: 1.5 /cvs/src/usr.sbin/lpr/lpc/lpc.h revision: 1.4 /cvs/src/usr.sbin/lpr/lpd/Makefile revision: 1.6 /cvs/src/usr.sbin/lpr/lpd/extern.h revision: 1.6 /cvs/src/usr.sbin/lpr/lpd/key.c revision: 1.21 /cvs/src/usr.sbin/lpr/lpd/lpd.8 revision: 1.47 /cvs/src/usr.sbin/lpr/lpd/lpd.c revision: 1.5 /cvs/src/usr.sbin/lpr/lpd/lpdchar.c revision: 1.6 /cvs/src/usr.sbin/lpr/lpd/modes.c revision: 1.44 /cvs/src/usr.sbin/lpr/lpd/printjob.c revision: 1.23 /cvs/src/usr.sbin/lpr/lpd/recvjob.c revision: 1.6 /cvs/src/usr.sbin/lpr/lpd/ttcompat.c revision: 1.4 /cvs/src/usr.sbin/lpr/lpq/Makefile revision: 1.10 /cvs/src/usr.sbin/lpr/lpq/lpq.1 revision: 1.16 /cvs/src/usr.sbin/lpr/lpq/lpq.c revision: 1.5 /cvs/src/usr.sbin/lpr/lpr/Makefile revision: 1.11 /cvs/src/usr.sbin/lpr/lpr/lpr.1 revision: 1.41 /cvs/src/usr.sbin/lpr/lpr/lpr.c revision: 1.6 /cvs/src/usr.sbin/lpr/lprm/Makefile revision: 1.10 /cvs/src/usr.sbin/lpr/lprm/lprm.1 revision: 1.17 /cvs/src/usr.sbin/lpr/lprm/lprm.c revision: 1.2 /cvs/src/usr.sbin/lpr/lptest/Makefile revision: 1.7 /cvs/src/usr.sbin/lpr/lptest/lptest.1 revision: 1.7 /cvs/src/usr.sbin/lpr/lptest/lptest.c revision: 1.3 /cvs/src/usr.sbin/lpr/pac/Makefile revision: 1.9 /cvs/src/usr.sbin/lpr/pac/pac.8 revision: 1.18 /cvs/src/usr.sbin/lpr/pac/pac.c The helper files are from (in common_source): revision: 1.11 /cvs/src/include/vis.h revision: 1.19 /cvs/src/lib/libc/gen/vis.c revision: 1.8 /cvs/src/lib/libc/string/strcat.c revision: 1.13 /cvs/src/lib/libc/string/strlcat.c revision: 1.11 /cvs/src/lib/libc/string/strlcpy.c Parts of the following files are used in Debian, for compatability functions revision: 1.27 /cvs/src/lib/libc/gen/getcap.c (in lpd) revision: 1.55 /cvs/src/lib/libc/net/rcmd.c (in common_source) lpr-2008.05.17.3+nmu1/common_source/0000755000000000000000000000000013416173536013477 5ustar lpr-2008.05.17.3+nmu1/common_source/common.c0000644000000000000000000003140311013655724015127 0ustar /* $OpenBSD: common.c,v 1.32 2007/09/02 15:19:38 deraadt Exp $ */ /* $NetBSD: common.c,v 1.21 2000/08/09 14:28:50 itojun Exp $ */ /* * 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. 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 #if 0 static const char sccsid[] = "@(#)common.c 8.5 (Berkeley) 4/28/95"; #else static const char rcsid[] = "$OpenBSD: common.c,v 1.32 2007/09/02 15:19:38 deraadt Exp $"; #endif #endif /* not lint */ #include #include #include #include #include #include #include #include #include #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; /* daemon 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 */ char *MS; /* stty flags to set if lp is a tty */ long MX; /* maximum number of blocks to copy */ char *NF; /* name of ditroff filter (per job) */ char *OF; /* name of output filter (created once) */ 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; /* restricted 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]; int remote; /* true if sending files to a remote host */ static int compar(const void *, const void *); /* * Create a TCP connection to host "rhost" at port "rport". * If rport == 0, then use the printer service port. * Most of this code comes from rcmd.c. */ int getport(char *rhost, int rport) { struct addrinfo hints, *res, *r; u_int timo = 1; int s, lport = IPPORT_RESERVED - 1; int error; int refuse, trial; char pbuf[NI_MAXSERV]; /* * Get the host address and port number to connect to. */ if (rhost == NULL) fatal("no remote host to connect to"); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (rport) snprintf(pbuf, sizeof(pbuf), "%d", rport); else snprintf(pbuf, sizeof(pbuf), "printer"); siginterrupt(SIGINT, 1); error = getaddrinfo(rhost, pbuf, &hints, &res); siginterrupt(SIGINT, 0); if (error) fatal("printer/tcp: %s", gai_strerror(error)); /* * Try connecting to the server. */ retry: s = -1; refuse = trial = 0; for (r = res; r; r = r->ai_next) { trial++; retryport: PRIV_START; s = rresvport_af(&lport, r->ai_family); PRIV_END; if (s < 0) { /* fall back to non-privileged port */ if (errno != EACCES || (s = socket(r->ai_family, SOCK_STREAM, 0)) < 0) { freeaddrinfo(res); return(-1); } } siginterrupt(SIGINT, 1); if (connect(s, r->ai_addr, r->ai_addrlen) < 0) { error = errno; siginterrupt(SIGINT, 0); (void)close(s); s = -1; errno = error; if (errno == EADDRINUSE) { lport--; goto retryport; } else if (errno == ECONNREFUSED) refuse++; continue; } else { siginterrupt(SIGINT, 0); break; } } if (s < 0 && trial == refuse && timo <= 16) { sleep(timo); timo *= 2; goto retry; } if (res) freeaddrinfo(res); /* Don't worry if we get an error from setsockopt(). */ trial = 1; setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &trial, sizeof(trial)); 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 getcfline(FILE *cfp) { int linel = 0; char *lp = line; int c; while ((c = getc(cfp)) != '\n' && linel+1d_name[0] != 'c' || d->d_name[1] != 'f') continue; /* daemon control files only */ PRIV_START; if (stat(d->d_name, &stbuf) < 0) { PRIV_END; continue; /* Doesn't exist */ } PRIV_END; q = (struct queue *)malloc(sizeof(struct queue)); if (q == NULL) goto errdone; q->q_time = stbuf.st_mtime; strlcpy(q->q_name, d->d_name, sizeof(q->q_name)); /* * Check to make sure the array has space left and * realloc the maximum size. */ if (nitems == arraysz) { struct queue **newqueue; size_t newarraysz = arraysz * 2; newqueue = (struct queue **)realloc(queue, newarraysz * sizeof(struct queue *)); if (newqueue == NULL) { free(q); goto errdone; } queue = newqueue; arraysz = newarraysz; } queue[nitems++] = q; } closedir(dirp); if (nitems) qsort(queue, nitems, sizeof(struct queue *), compar); *namelist = queue; return(nitems); errdone: if (queue != NULL) { while (nitems--) free(queue[nitems]); free(queue); } closedir(dirp); return(-1); } /* * Compare modification times. */ static int compar(const void *v1, const void *v2) { struct queue *p1 = *(struct queue **)v1; struct queue *p2 = *(struct queue **)v2; return(p1->q_time - p2->q_time); } /* * Figure out whether the local machine is the same * as the remote machine (RM) entry (if it exists). */ char * checkremote(void) { char lname[NI_MAXHOST], rname[NI_MAXHOST]; struct addrinfo hints, *res, *res0; static char errbuf[128]; int error; struct ifaddrs *ifap, *ifa; const int niflags = NI_NUMERICHOST; #ifdef __KAME__ struct sockaddr_in6 sin6; struct sockaddr_in6 *sin6p; #endif remote = 0; /* assume printer is local on failure */ if (RM == NULL || *RM == '\0') return NULL; /* get the local interface addresses */ siginterrupt(SIGINT, 1); if (getifaddrs(&ifap) < 0) { (void)snprintf(errbuf, sizeof(errbuf), "unable to get local interface address: %s", strerror(errno)); siginterrupt(SIGINT, 0); return errbuf; } siginterrupt(SIGINT, 0); /* get the remote host addresses (RM) */ memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; res = NULL; siginterrupt(SIGINT, 1); error = getaddrinfo(RM, NULL, &hints, &res0); siginterrupt(SIGINT, 0); if (error) { (void)snprintf(errbuf, sizeof(errbuf), "unable to resolve remote machine %s: %s", RM, gai_strerror(error)); freeifaddrs(ifap); return errbuf; } remote = 1; /* assume printer is remote */ for (res = res0; res; res = res->ai_next) { siginterrupt(SIGINT, 1); error = getnameinfo(res->ai_addr, res->ai_addrlen, rname, sizeof(rname), NULL, 0, niflags); siginterrupt(SIGINT, 0); if (error != 0) continue; for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if( ifa->ifa_addr == NULL ) /* Not an address, so we continue */ continue; #ifdef __KAME__ sin6p = (struct sockaddr_in6 *)ifa->ifa_addr; if (ifa->ifa_addr->sa_family == AF_INET6 && /* ifa->ifa_addr->sa_len == sizeof(sin6) && */ IN6_IS_ADDR_LINKLOCAL(&sin6p->sin6_addr) && *(u_int16_t *)&sin6p->sin6_addr.s6_addr[2]) { /* kame scopeid hack */ memcpy(&sin6, ifa->ifa_addr, sizeof(sin6)); sin6.sin6_scope_id = ntohs(*(u_int16_t *)&sin6p->sin6_addr.s6_addr[2]); sin6.sin6_addr.s6_addr[2] = 0; sin6.sin6_addr.s6_addr[3] = 0; siginterrupt(SIGINT, 1); error = getnameinfo((struct sockaddr *)&sin6, /*sin6.sin6_len*/sizeof(struct sockaddr_in6), lname, sizeof(lname), NULL, 0, niflags); siginterrupt(SIGINT, 0); if (error != 0) continue; } else #endif siginterrupt(SIGINT, 1); error = getnameinfo(ifa->ifa_addr, /*ifa->ifa_addr->sa_len*/sizeof(struct sockaddr_in), lname, sizeof(lname), NULL, 0, niflags); siginterrupt(SIGINT, 0); if (error != 0) continue; if (strcmp(rname, lname) == 0) { remote = 0; goto done; } } } done: freeaddrinfo(res0); freeifaddrs(ifap); return NULL; } /* sleep n milliseconds */ void delay(int n) { struct timeval tdelay; if (n <= 0 || n > 10000) fatal("unreasonable delay period (%d)", n); tdelay.tv_sec = n / 1000; tdelay.tv_usec = n * 1000 % 1000000; (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tdelay); } void fatal(const char *msg, ...) { extern char *__progname; va_list ap; va_start(ap, msg); if (from != host) (void)printf("%s: ", host); (void)printf("%s: ", __progname); if (printer) (void)printf("%s: ", printer); (void)vprintf(msg, ap); va_end(ap); (void)putchar('\n'); exit(1); } int safe_open(const char *path, int flags, mode_t mode) { int fd, serrno; struct stat stbuf; if ((fd = open(path, flags|O_NONBLOCK, mode)) < 0 || fstat(fd, &stbuf) < 0) { if (fd >= 0) { serrno = errno; close(fd); errno = serrno; } return (-1); } if (!S_ISREG(stbuf.st_mode)) { close(fd); errno = EACCES; return (-1); } if (mode) (void)fchmod(fd, mode); return (fd); } /* * Returns the uid of user "lp" */ int lprGetUID(void) { struct passwd *user; user = getpwnam( "lp" ); if( user == 0 ){ warn( "Cannot fetch UID of user lp. Assuming UID(lp)==7" ); return 7; } return user->pw_uid; } lpr-2008.05.17.3+nmu1/common_source/common_vars.c0000644000000000000000000000505007666757625016207 0ustar /* $OpenBSD: common_vars.c,v 1.3 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: common.c,v 1.15 1999/09/26 10:32:27 mrg Exp $ */ /* * 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. 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 const char rcsid[] = "$OpenBSD: common_vars.c,v 1.3 2003/06/02 23:36:53 millert Exp $"; #endif /* not lint */ #include #include "pathnames.h" char *name; /* program name */ char *printer; /* printer name */ char host[MAXHOSTNAMELEN+1]; /* host machine name */ char *from = host; /* client's machine name */ char *printcapdb[2] = { _PATH_PRINTCAP, 0 }; char *bp; /* pointer into printcap buffer. */ u_int wait_time = 300; /* time out after 5 minutes by default */ uid_t real_uid, effective_uid; gid_t real_gid, effective_gid; lpr-2008.05.17.3+nmu1/common_source/displayq.c0000644000000000000000000003040211013655724015463 0ustar /* $OpenBSD: displayq.c,v 1.29 2007/04/08 23:11:37 stevesk Exp $ */ /* $NetBSD: displayq.c,v 1.21 2001/08/30 00:51:50 itojun Exp $ */ /* * 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. 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 #if 0 static const char sccsid[] = "@(#)displayq.c 8.4 (Berkeley) 4/28/95"; #else static const char rcsid[] = "$OpenBSD: displayq.c,v 1.29 2007/04/08 23:11:37 stevesk Exp $"; #endif #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vis.h" #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 termwidth; static int col; /* column on screen */ static char current[NAME_MAX]; /* current file being printed */ static char file[NAME_MAX]; /* print file name */ static int first; /* first file in ``files'' column? */ static int lflag; /* long output option */ static off_t totsize; /* total print job size in bytes */ static const char *head0 = "Rank Owner Job Files"; static const char *head1 = "Total Size\n"; static void alarmer(int); static void inform(char *, int); /* * Display the current state of the queue. Format = 1 if long format. */ void displayq(int format) { struct queue *q; int i, rank, nitems, fd, ret, len; char *cp, *ecp, *p; struct queue **queue; struct winsize win; struct stat statb; FILE *fp; termwidth = 80; if (isatty(STDOUT_FILENO)) { if ((p = getenv("COLUMNS")) != NULL) termwidth = atoi(p); else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 && win.ws_col > 0) termwidth = win.ws_col; } if (termwidth < 60) termwidth = 60; lflag = format; totsize = 0; 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, DEFLP, &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()) != NULL) printf("Warning: %s\n", cp); /* * Print out local queue * Find all the control files in the spooling directory */ PRIV_START; if (chdir(SD) < 0) fatal("cannot chdir to spooling directory"); PRIV_END; if ((nitems = getq(&queue)) < 0) fatal("cannot examine spooling area"); PRIV_START; ret = stat(LO, &statb); PRIV_END; if (ret >= 0) { if (statb.st_mode & S_IXUSR) { if (remote) printf("%s: ", host); printf("Warning: %s is down: ", printer); PRIV_START; fd = safe_open(ST, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd >= 0 && flock(fd, LOCK_SH) == 0) { 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 & S_IXGRP) { if (remote) printf("%s: ", host); printf("Warning: %s queue is turned off\n", printer); } } if (nitems) { PRIV_START; fd = safe_open(LO, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) { if (fd >= 0) close(fd); nodaemon(); } else { /* get daemon pid */ cp = current; ecp = cp + sizeof(current) - 1; while ((i = getc(fp)) != EOF && i != '\n') { if (cp < ecp) *cp++ = i; } *cp = '\0'; i = atoi(current); if (i <= 0) { ret = -1; } else { PRIV_START; ret = kill(i, 0); PRIV_END; } if (ret < 0 && errno != EPERM) { nodaemon(); } else { /* read current file name */ cp = current; ecp = cp + sizeof(current) - 1; while ((i = getc(fp)) != EOF && i != '\n') { if (cp < ecp) *cp++ = i; } *cp = '\0'; /* * Print the status file. */ if (remote) printf("%s: ", host); PRIV_START; fd = safe_open(ST, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd >= 0 && flock(fd, LOCK_SH) == 0) { 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(); /* The currently printed job is treated specially. */ if (!remote && current[0] != '\0') inform(current, 0); for (i = 0, rank = 1; i < nitems; i++) { q = queue[i]; if (remote || strcmp(current, q->q_name) != 0) inform(q->q_name, rank++); free(q); } } free(queue); if (!remote) { 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)snprintf(line, sizeof(line), "%c%s", format + '\3', RP); cp = line; cp += strlen(cp); for (i = 0; i < requests && cp - line < sizeof(line) - 1; i++) { len = line + sizeof(line) - cp; if (snprintf(cp, len, " %d", requ[i]) >= len) { cp += strlen(cp); break; } cp += strlen(cp); } for (i = 0; i < users && cp - line < sizeof(line) - 1; i++) { len = line + sizeof(line) - cp; if (snprintf(cp, len, " %s", user[i]) >= len) { cp += strlen(cp); break; } } if (cp-line < sizeof(line) - 1) strlcat(line, "\n", sizeof(line)); else line[sizeof(line) - 2] = '\n'; fd = getport(RM, 0); if (fd < 0) { if (from != host) printf("%s: ", host); (void)printf("connection to %s is down\n", RM); } else { struct sigaction osa, nsa; char *visline; int n = 0; i = strlen(line); if (write(fd, line, i) != i) fatal("Lost connection"); memset(&nsa, 0, sizeof(nsa)); nsa.sa_handler = alarmer; sigemptyset(&nsa.sa_mask); nsa.sa_flags = 0; (void)sigaction(SIGALRM, &nsa, &osa); alarm(wait_time); if ((visline = (char *)malloc(4 * sizeof(line) + 1)) == NULL) fatal("Out of memory"); while ((i = read(fd, line, sizeof(line))) > 0) { n = strvisx(visline, line, i, VIS_SAFE|VIS_NOSLASH); (void)fwrite(visline, 1, n, stdout); alarm(wait_time); } /* XXX some LPR implementations may not end stream with '\n' */ if (n > 0 && visline[n-1] != '\n') putchar('\n'); alarm(0); (void)sigaction(SIGALRM, &osa, NULL); free(visline); (void)close(fd); } } static void alarmer(int s) { /* nothing */ } /* * Print a warning message if there is no daemon present. */ void nodaemon(void) { if (remote) printf("\n%s: ", host); puts("Warning: no daemon present"); current[0] = '\0'; } /* * Print the header for the short listing format */ void header(void) { printf(head0); col = strlen(head0)+1; blankfill(termwidth - (80 - SIZCOL)); printf(head1); } static void inform(char *cf, int rank) { int fd, j; FILE *cfp = NULL; /* * There's a chance the control file has gone away * in the meantime; if this is the case just keep going */ PRIV_START; fd = safe_open(cf, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd < 0 || (cfp = fdopen(fd, "r")) == NULL) { if (fd >= 0) close(fd); return; } j = 0; while (getcfline(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)strlcpy(file, line+1, sizeof(file)); j++; continue; case 'N': show(line+1, file, j); file[0] = '\0'; j = 0; } } fclose(cfp); if (!lflag) { blankfill(termwidth - (80 - SIZCOL)); printf("%lld bytes\n", (long long)totsize); totsize = 0; } } int inlist(char *name, char *file) { int *r, n; 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(char *nfile, char *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(int n) { while (col++ < n) putchar(' '); } /* * Give the abbreviated dump of the file names */ void dump(char *nfile, char *file, int copies) { int 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) >= (termwidth - (80 - SIZCOL)) - 4) { if (col < (termwidth - (80 - SIZCOL))) { printf(" ..."), col += 4; blankfill(termwidth - (80 - SIZCOL)); } } else { if (first) first = 0; else printf(", "); printf("%s", nfile); col += n+fill; } PRIV_START; if (*file && !stat(file, &lbuf)) totsize += copies * lbuf.st_size; PRIV_END; } /* * Print the long info about the file */ void ldump(char *nfile, char *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)==0) printf(" %8lld bytes -- %s", (long long)lbuf.st_size, ctime(&lbuf.st_mtime)); else printf(" ??? bytes\n"); } /* * Print the job's rank in the queue, * update col for screen management */ void prank(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); } lpr-2008.05.17.3+nmu1/common_source/getcap.c0000644000000000000000000004641711014414542015105 0ustar /* $OpenBSD: getcap.c,v 1.27 2006/05/15 04:18:19 hugh Exp $ */ /*- ***** NOTE: Parts of this file are from src/lib/libc/gen/getcap.c. The entire file is NOT included. ***** * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Casey Leedom of Lawrence Livermore National Laboratory. * * 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. 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. */ #include #include #include #include #include #include #include #include #include #include "lp.h" #define BFRAG 1024 #define BSIZE 1024 #define ESC ('[' & 037) /* ASCII ESC */ #define MAX_RECURSION 32 /* maximum getent recursion */ #define SFRAG 100 /* cgetstr mallocs in SFRAG chunks */ #define RECOK (char)0 #define TCERR (char)1 #define SHADOW (char)2 static size_t topreclen; /* toprec length */ static char *toprec; /* Additional record specified by cgetset() */ static int gottoprec; /* Flag indicating retrieval of toprecord */ static int getent (char **, u_int *, char **, int, const char *, int, char *); static int nfcmp (const char *, char *); /* * Cgetcap searches the capability record buf for the capability cap with * type `type'. A pointer to the value of cap is returned on success, NULL * if the requested capability couldn't be found. * * Specifying a type of ':' means that nothing should follow cap (:cap:). * In this case a pointer to the terminating ':' or NUL will be returned if * cap is found. * * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator) * return NULL. */ char * cgetcap(char *buf, const char *cap, int type) { char *bp; const char *cp; bp = buf; for (;;) { /* * Skip past the current capability field - it's either the * name field if this is the first time through the loop, or * the remainder of a field whose name failed to match cap. */ for (;;) if (*bp == '\0') return (NULL); else if (*bp++ == ':') break; /* * Try to match (cap, type) in buf. */ for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++) continue; if (*cp != '\0') continue; if (*bp == '@') return (NULL); if (type == ':') { if (*bp != '\0' && *bp != ':') continue; return(bp); } if (*bp != type) continue; bp++; return (*bp == '@' ? NULL : bp); } /* NOTREACHED */ } /* * Cgetent extracts the capability record name from the NULL terminated file * array db_array and returns a pointer to a malloc'd copy of it in buf. * Buf must be retained through all subsequent calls to cgetcap, cgetnum, * cgetflag, and cgetstr, but may then be free'd. 0 is returned on success, * -1 if the requested record couldn't be found, -2 if a system error was * encountered (couldn't open/read a file, etc.), and -3 if a potential * reference loop is detected. */ int cgetent(char **buf, char **db_array, const char *name) { u_int dummy; return (getent(buf, &dummy, db_array, -1, name, 0, NULL)); } /* * Getent implements the functions of cgetent. If fd is non-negative, * *db_array has already been opened and fd is the open file descriptor. We * do this to save time and avoid using up file descriptors for tc= * recursions. * * Getent returns the same success/failure codes as cgetent. On success, a * pointer to a malloc'ed capability record with all tc= capabilities fully * expanded and its length (not including trailing ASCII NUL) are left in * *cap and *len. * * Basic algorithm: * + Allocate memory incrementally as needed in chunks of size BFRAG * for capability buffer. * + Recurse for each tc=name and interpolate result. Stop when all * names interpolated, a name can't be found, or depth exceeds * MAX_RECURSION. */ static int getent(char **cap, u_int *len, char **db_array, int fd, const char *name, int depth, char *nfield) { char *r_end, *rp, **db_p; int myfd, eof, foundit, opened, retval, clen; char *record, *cbuf; int tc_not_resolved; char pbuf[PATH_MAX]; /* * Return with ``loop detected'' error if we've recursed more than * MAX_RECURSION times. */ if (depth > MAX_RECURSION) return (-3); opened = 0; /* * Check if we have a top record from cgetset(). */ if (depth == 0 && toprec != NULL && cgetmatch(toprec, name) == 0) { opened++; if ((record = malloc (topreclen + 1 + BFRAG)) == NULL) return (-2); memcpy(record, toprec, topreclen + 1); myfd = 0; db_p = db_array; rp = record + topreclen + 1; r_end = rp + BFRAG; goto tc_exp; } /* * Allocate first chunk of memory. */ if ((record = malloc(BFRAG)) == NULL) return (-2); r_end = record + BFRAG; foundit = 0; /* * Loop through database array until finding the record. */ for (db_p = db_array; *db_p != NULL; db_p++) { eof = 0; /* * Open database if not already open. */ if (fd >= 0) { (void)lseek(fd, (off_t)0, SEEK_SET); myfd = 0; opened++; } else { fd = open(*db_p, O_RDONLY, 0); if (fd < 0) { /* No error on unfound file. */ continue; } myfd = 1; opened++; } /* * Find the requested capability record ... */ { char buf[BUFSIZ]; char *b_end, *bp; int c; /* * Loop invariants: * There is always room for one more character in record. * R_end always points just past end of record. * Rp always points just past last character in record. * B_end always points just past last character in buf. * Bp always points at next character in buf. */ b_end = buf; bp = buf; for (;;) { /* * Read in a line implementing (\, newline) * line continuation. */ rp = record; for (;;) { if (bp >= b_end) { int n; n = read(fd, buf, sizeof(buf)); if (n <= 0) { if (myfd) (void)close(fd); if (n < 0) { free(record); return (-2); } else { fd = -1; eof = 1; break; } } b_end = buf+n; bp = buf; } c = *bp++; if (c == '\n') { if (rp > record && *(rp-1) == '\\') { rp--; continue; } else break; } *rp++ = c; /* * Enforce loop invariant: if no room * left in record buffer, try to get * some more. */ if (rp >= r_end) { u_int pos; size_t newsize; char *nrecord; pos = rp - record; newsize = r_end - record + BFRAG; nrecord = realloc(record, newsize); if (nrecord == NULL) { if (record) free(record); if (myfd) (void)close(fd); errno = ENOMEM; return (-2); } record = nrecord; r_end = record + newsize; rp = record + pos; } } /* loop invariant lets us do this */ *rp++ = '\0'; /* * If encountered EOF check next file. */ if (eof) break; /* * Toss blank lines and comments. */ if (*record == '\0' || *record == '#') continue; /* * See if this is the record we want ... */ if (cgetmatch(record, name) == 0) { if (nfield == NULL || !nfcmp(nfield, record)) { foundit = 1; break; /* found it! */ } } } } if (foundit) break; } if (!foundit) { free(record); return (opened ? -1 : -2); } /* * Got the capability record, but now we have to expand all tc=name * references in it ... */ tc_exp: { char *s; u_int ilen; int diff, iret, tclen; char *ibuf, *icap, *scan, *tc, *tcstart, *tcend; /* * Loop invariants: * There is room for one more character in record. * R_end points just past end of record. * Rp points just past last character in record. * Scan points at remainder of record that needs to be * scanned for tc=name constructs. */ scan = record; tc_not_resolved = 0; for (;;) { if ((tc = cgetcap(scan, "tc", '=')) == NULL) break; /* * Find end of tc=name and stomp on the trailing `:' * (if present) so we can use it to call ourselves. */ s = tc; for (;;){ if (*s == '\0') break; else if (*s++ == ':') { *(s - 1) = '\0'; break; } } tcstart = tc - 3; tclen = s - tcstart; tcend = s; iret = getent(&icap, &ilen, db_p, fd, tc, depth+1, NULL); if (iret != 0) { /* an error */ if (iret < -1) { if (myfd) (void)close(fd); free(record); return (iret); } if (iret == 1) tc_not_resolved = 1; /* couldn't resolve tc */ if (iret == -1) { *(s - 1) = ':'; scan = s - 1; tc_not_resolved = 1; continue; } } /* not interested in name field of tc'ed record */ s = ibuf = icap; for (;;) if (*s == '\0') break; else if (*s++ == ':') break; ilen -= s - icap; icap = s; /* make sure interpolated record is `:'-terminated */ s += ilen; if (*(s-1) != ':') { *s = ':'; /* overwrite NUL with : */ ilen++; } /* * Make sure there's enough room to insert the * new record. */ diff = ilen - tclen; if (diff >= r_end - rp) { u_int pos, tcpos, tcposend; size_t newsize; char *nrecord; pos = rp - record; newsize = r_end - record + diff + BFRAG; tcpos = tcstart - record; tcposend = tcend - record; nrecord = realloc(record, newsize); if (nrecord == NULL) { if (record) free(record); if (myfd) (void)close(fd); free(ibuf); errno = ENOMEM; return (-2); } record = nrecord; r_end = record + newsize; rp = record + pos; tcstart = record + tcpos; tcend = record + tcposend; } /* * Insert tc'ed record into our record. */ s = tcstart + ilen; memmove(s, tcend, rp - tcend); memmove(tcstart, icap, ilen); rp += diff; free(ibuf); /* * Start scan on `:' so next cgetcap works properly * (cgetcap always skips first field). */ scan = s-1; } } /* * Close file (if we opened it), give back any extra memory, and * return capability, length and success. */ if (myfd) (void)close(fd); *len = rp - record - 1; /* don't count NUL */ if (r_end > rp) { char *nrecord; if ((nrecord = realloc(record, (size_t)(rp - record))) == NULL) { if (record) free(record); errno = ENOMEM; return (-2); } record = nrecord; } *cap = record; if (tc_not_resolved) return (1); return (0); } /* * Cgetmatch will return 0 if name is one of the names of the capability * record buf, -1 if not. */ int cgetmatch(char *buf, const char *name) { char *bp; const char *np; if( name == NULL || *name == '\0' ) return (-1); /* * Start search at beginning of record. */ bp = buf; for (;;) { /* * Try to match a record name. */ np = name; for (;;) if (*np == '\0') { if (*bp == '|' || *bp == ':' || *bp == '\0') return (0); else break; } else if (*bp++ != *np++) break; /* * Match failed, skip to next name in record. */ bp--; /* a '|' or ':' may have stopped the match */ for (;;) if (*bp == '\0' || *bp == ':') return (-1); /* match failed totally */ else if (*bp++ == '|') break; /* found next name */ } } static FILE *pfp; static int slash; static char **dbp; int cgetclose(void) { if (pfp != NULL) { (void)fclose(pfp); pfp = NULL; } dbp = NULL; gottoprec = 0; slash = 0; return(0); } /* * Cgetnext() gets either the first or next entry in the logical database * specified by db_array. It returns 0 upon completion of the database, 1 * upon returning an entry with more remaining, and -1 if an error occurs. */ int cgetnext(char **bp, char **db_array) { size_t len = 0; int status, done; char *line = NULL, *np, buf[BSIZE], nbuf[BSIZE]; u_int dummy; if (dbp == NULL) dbp = db_array; if (pfp == NULL && (pfp = fopen(*dbp, "r")) == NULL) { (void)cgetclose(); return (-1); } for (;;) { if (toprec && !gottoprec) { gottoprec = 1; line = toprec; } else { if (getline(&line, &len, pfp) == -1) { if (ferror(pfp)) { (void)cgetclose(); return (-1); } else { (void)fclose(pfp); pfp = NULL; if (*++dbp == NULL) { (void)cgetclose(); return (0); } else if ((pfp = fopen(*dbp, "r")) == NULL) { (void)cgetclose(); return (-1); } else continue; } } else line[len - 1] = '\0'; /* XXX - assumes newline */ if (len == 1) { slash = 0; continue; } if (isspace(*line) || *line == ':' || *line == '#' || slash) { if (line[len - 2] == '\\') slash = 1; else slash = 0; continue; } if (line[len - 2] == '\\') slash = 1; else slash = 0; } /* * Line points to a name line. */ done = 0; np = nbuf; for (;;) { len = strcspn(line, ":\\"); if (line[len] == ':') { done = 1; ++len; } /* copy substring */ if (len >= sizeof(nbuf) - (np - nbuf)) { (void)cgetclose(); return (-1); } memcpy(np, line, len); np += len; if (done) { *np = '\0'; break; } else { /* name field extends beyond the line */ if (getline(&line, &len, pfp) == -1) { if (ferror(pfp)) { (void)cgetclose(); return (-1); } /* Move on to next file. */ (void)fclose(pfp); pfp = NULL; ++dbp; /* NUL terminate nbuf. */ *np = '\0'; break; } else line[len - 1] = '\0'; } } len = strcspn(nbuf, "|:"); memcpy(buf, nbuf, len); buf[len] = '\0'; /* * XXX * Last argument of getent here should be nbuf if we want true * sequential access in the case of duplicates. * With NULL, getent will return the first entry found * rather than the duplicate entry record. This is a * matter of semantics that should be resolved. */ status = getent(bp, &dummy, db_array, -1, buf, 0, NULL); if (status == -2 || status == -3) (void)cgetclose(); return (status + 1); } /* NOTREACHED */ } /* * Cgetstr retrieves the value of the string capability cap from the * capability record pointed to by buf. A pointer to a decoded, NUL * terminated, malloc'd copy of the string is returned in the char * * pointed to by str. The length of the string not including the trailing * NUL is returned on success, -1 if the requested string capability * couldn't be found, -2 if a system error was encountered (storage * allocation failure). */ int cgetstr(char *buf, const char *cap, char **str) { u_int m_room; char *bp, *mp; int len; char *mem; /* * Find string capability cap */ bp = cgetcap(buf, cap, '='); if (bp == NULL) return (-1); /* * Conversion / storage allocation loop ... Allocate memory in * chunks SFRAG in size. */ if ((mem = malloc(SFRAG)) == NULL) return (-2); /* couldn't even allocate the first fragment */ m_room = SFRAG; mp = mem; while (*bp != ':' && *bp != '\0') { /* * Loop invariants: * There is always room for one more character in mem. * Mp always points just past last character in mem. * Bp always points at next character in buf. */ if (*bp == '^') { bp++; if (*bp == ':' || *bp == '\0') break; /* drop unfinished escape */ *mp++ = *bp++ & 037; } else if (*bp == '\\') { bp++; if (*bp == ':' || *bp == '\0') break; /* drop unfinished escape */ if ('0' <= *bp && *bp <= '7') { int n, i; n = 0; i = 3; /* maximum of three octal digits */ do { n = n * 8 + (*bp++ - '0'); } while (--i && '0' <= *bp && *bp <= '7'); *mp++ = n; } else switch (*bp++) { case 'b': case 'B': *mp++ = '\b'; break; case 't': case 'T': *mp++ = '\t'; break; case 'n': case 'N': *mp++ = '\n'; break; case 'f': case 'F': *mp++ = '\f'; break; case 'r': case 'R': *mp++ = '\r'; break; case 'e': case 'E': *mp++ = ESC; break; case 'c': case 'C': *mp++ = ':'; break; default: /* * Catches '\', '^', and * everything else. */ *mp++ = *(bp-1); break; } } else *mp++ = *bp++; m_room--; /* * Enforce loop invariant: if no room left in current * buffer, try to get some more. */ if (m_room == 0) { size_t size = mp - mem; char *nmem; if ((nmem = realloc(mem, size + SFRAG)) == NULL) { if (mem) free(mem); return (-2); } mem = nmem; m_room = SFRAG; mp = mem + size; } } *mp++ = '\0'; /* loop invariant let's us do this */ m_room--; len = mp - mem - 1; /* * Give back any extra memory and return value and success. */ if (m_room != 0) { char *nmem; if ((nmem = realloc(mem, (size_t)(mp - mem))) == NULL) { if (mem) free(mem); return (-2); } mem = nmem; } *str = mem; return (len); } /* * Cgetnum retrieves the value of the numeric capability cap from the * capability record pointed to by buf. The numeric value is returned in * the long pointed to by num. 0 is returned on success, -1 if the requested * numeric capability couldn't be found. */ int cgetnum(char *buf, const char *cap, long *num) { long n; int base, digit; char *bp; /* * Find numeric capability cap */ bp = cgetcap(buf, cap, '#'); if (bp == NULL) return (-1); /* * Look at value and determine numeric base: * 0x... or 0X... hexadecimal, * else 0... octal, * else decimal. */ if (*bp == '0') { bp++; if (*bp == 'x' || *bp == 'X') { bp++; base = 16; } else base = 8; } else base = 10; /* * Conversion loop ... */ n = 0; for (;;) { if ('0' <= *bp && *bp <= '9') digit = *bp - '0'; else if ('a' <= *bp && *bp <= 'f') digit = 10 + *bp - 'a'; else if ('A' <= *bp && *bp <= 'F') digit = 10 + *bp - 'A'; else break; if (digit >= base) break; n = n * base + digit; bp++; } /* * Return value and success. */ *num = n; return (0); } /* * Compare name field of record. */ static int nfcmp(const char *nf, char *rec) { char *cp, tmp; int ret; for (cp = rec; *cp != ':'; cp++) ; tmp = *(cp + 1); *(cp + 1) = '\0'; ret = strcmp(nf, rec); *(cp + 1) = tmp; return (ret); } lpr-2008.05.17.3+nmu1/common_source/lp.h0000644000000000000000000001436311554307314014264 0ustar /* $OpenBSD: lp.h,v 1.14 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: lp.h,v 1.14 2000/04/16 14:43:58 mrg Exp $ */ /* * 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. 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.2 (Berkeley) 4/28/95 */ #include #include #include #include #if !defined(LOGIN_NAME_MAX) && defined(MAXLOGNAME) #define LOGIN_NAME_MAX MAXLOGNAME #endif #ifndef N_TTY #define N_TTY TTYDISC #endif /* * 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; /* daemon 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 char *MS; /* stty flags to set if lp is a tty */ 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 *printer; /* printer name */ /* host machine name */ extern char host[MAXHOSTNAMELEN]; extern char *from; /* client's machine name */ extern int remote; /* true if sending files to a remote host */ extern char *printcapdb[]; /* printcap database array */ extern u_int wait_time; /* time to wait for remote responses */ extern uid_t real_uid, effective_uid; extern gid_t real_gid, effective_gid; extern volatile sig_atomic_t gotintr; /* * 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 */ }; /* * Macros to raise/lower permissions. */ #define PRIV_START do { \ int save_errno = errno; \ (void)seteuid(effective_uid); \ (void)setegid(effective_gid); \ errno = save_errno; \ } while (0) #define PRIV_END do { \ int save_errno = errno; \ (void)setegid(real_gid); \ (void)seteuid(real_uid); \ errno = save_errno; \ } while (0) #include __BEGIN_DECLS struct dirent; void blankfill(int); char *checkremote(void); int chk(char *); void displayq(int); void dump(char *, char *, int); void fatal(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); int getcfline(FILE *); int getport(char *, int); int getq(struct queue ***); void header(void); int inlist(char *, char *); int iscf(const struct dirent *); int isowner(char *, char *); void ldump(char *, char *, int); void prank(int); void process(char *); void rmjob(void); void rmremote(void); void show(char *, char *, int); int startdaemon(char *); void nodaemon(void); void delay(int); int safe_open(const char *, int, mode_t); char *cgetcap (char *, const char *, int); int cgetent (char **, char **, const char *); int cgetmatch (char *, const char *); int cgetnext (char **, char **); int cgetstr (char *, const char *, char **); int cgetunum (char *, const char *, long *); int cgetnum(char *, const char *, long *); size_t strlcpy(char *dst, const char *src, size_t siz); size_t strlcat(char *dst, const char *src, size_t siz); int cgetclose(); int lprGetUID(void); __END_DECLS lpr-2008.05.17.3+nmu1/common_source/lp.local.h0000644000000000000000000000531510176611664015357 0ustar /* $OpenBSD: lp.local.h,v 1.4 2003/06/02 23:36:53 millert Exp $ */ /* * 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. 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 0 #define DEFMAXCOPIES 0 #define DEFFF "\f" #define DEFWIDTH 132 #define DEFLENGTH 66 #define DEFUID "lp" #define DEFNUID lprGetUID() /* * 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 lpr-2008.05.17.3+nmu1/common_source/pathnames.h0000644000000000000000000000444011013667452015626 0ustar /* $OpenBSD: pathnames.h,v 1.4 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: pathnames.h,v 1.5 1995/11/28 19:43:27 jtc Exp $ */ /* * 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. 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/lp0" #define _PATH_DEFSPOOL "/var/spool/lpd" #define _PATH_HOSTSEQUIV "/etc/hosts.equiv" #define _PATH_HOSTSLPD "/etc/hosts.lpd" #define _PATH_MASTERLOCK "/var/run/lpd.pid" #define _PATH_PR "/usr/bin/pr" #define _PATH_PRINTCAP "/etc/printcap" #define _PATH_SOCKETNAME "/dev/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" lpr-2008.05.17.3+nmu1/common_source/rmjob.c0000644000000000000000000002333411013655724014754 0ustar /* $OpenBSD: rmjob.c,v 1.17 2007/04/07 21:12:12 stevesk Exp $ */ /* $NetBSD: rmjob.c,v 1.16 2000/04/16 14:43:58 mrg Exp $ */ /* * 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. 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 #if 0 static const char sccsid[] = "@(#)rmjob.c 8.2 (Berkeley) 4/28/95"; #else static const char rcsid[] = "$OpenBSD: rmjob.c,v 1.17 2007/04/07 21:12:12 stevesk Exp $"; #endif #endif /* not lint */ #include #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[NAME_MAX]; /* active control file name */ static void do_unlink(char *); static void alarmer(int); static int lockchk(char *); void rmjob(void) { 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, DEFLP, &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()) != NULL) 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; } PRIV_START; if (chdir(SD) < 0) fatal("cannot chdir to spool directory"); if ((nitems = scandir(".", &files, iscf, NULL)) < 0) fatal("cannot access spool directory"); PRIV_END; if (nitems) { /* * Check for an active printer daemon. If one is running * and it is reading our file, kill it, then remove stuff. * Lastly, restart the daemon if it is not (or no longer) * running. */ if (lockchk(LO) && chk(current)) { PRIV_START; assasinated = kill(cur_daemon, SIGINT) == 0; PRIV_END; if (!assasinated) fatal("cannot kill printer daemon (pid: %d)", (int)cur_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"); 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. */ static int lockchk(char *s) { FILE *fp = NULL; int fd, i, n; /* NOTE: lock file is owned by root, not the user. */ PRIV_START; fd = safe_open(s, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) { if (fd >= 0) close(fd); if (errno == EACCES) fatal("can't access lock file"); else return(0); } if (!getcfline(fp)) { (void)fclose(fp); return(0); /* no daemon present */ } cur_daemon = atoi(line); if (kill(cur_daemon, 0) < 0 && errno != EPERM) { (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(char *file) { FILE *cfp = NULL; int fd; if (!chk(file)) return; PRIV_START; fd = safe_open(file, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd < 0 || (cfp = fdopen(fd, "r")) == NULL) { if (fd >= 0) close(fd); fatal("cannot open %s", file); } while (getcfline(cfp)) { switch (line[0]) { case 'U': /* unlink associated files */ if (strchr(line+1, '/') || strncmp(line+1, "df", 2)) break; do_unlink(line+1); } } (void)fclose(cfp); do_unlink(file); } static void do_unlink(char *file) { int ret; if (from != host) printf("%s: ", host); PRIV_START; ret = unlink(file); PRIV_END; printf(ret ? "cannot dequeue %s\n" : "%s dequeued\n", file); } /* * Do the dirty work in checking */ int chk(char *file) { int *r, n, fd; char **u, *cp; FILE *cfp = NULL; /* * 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. */ PRIV_START; fd = safe_open(file, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd < 0 || (cfp = fdopen(fd, "r")) == NULL) { if (fd >= 0) close(fd); return(0); } while (getcfline(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(char *owner, char *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(void) { char *cp; int i, rem; size_t n; char buf[BUFSIZ]; if (!remote) 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); /* the trailing space will be replaced with a newline later */ n = snprintf(buf, sizeof(buf), "\5%s %s ", RP, all ? "-all" : person); if (n == -1 || n >= sizeof(buf)) goto bad; cp = buf + n; for (i = 0; i < users; i++) { n = strlcpy(cp, user[i], sizeof(buf) - (cp - buf + 1)); if (n >= sizeof(buf) - (cp - buf + 1)) goto bad; cp += n; *cp++ = ' '; } *cp = '\0'; for (i = 0; i < requests; i++) { n = snprintf(cp, sizeof(buf) - (cp - buf), "%d ", requ[i]); if (n == -1 || n >= sizeof(buf) - (cp - buf)) goto bad; cp += n; } cp[-1] = '\n'; /* replace space with newline, leave the NUL */ rem = getport(RM, 0); if (rem < 0) { if (from != host) printf("%s: ", host); printf("connection to %s is down\n", RM); } else { struct sigaction osa, nsa; memset(&nsa, 0, sizeof(nsa)); nsa.sa_handler = alarmer; sigemptyset(&nsa.sa_mask); nsa.sa_flags = 0; (void)sigaction(SIGALRM, &nsa, &osa); alarm(wait_time); 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); alarm(0); (void)sigaction(SIGALRM, &osa, NULL); (void)close(rem); } return; bad: printf("remote buffer too large\n"); return; } static void alarmer(int s) { /* nothing */ } /* * Return 1 if the filename begins with 'cf' */ int iscf(const struct dirent *d) { return(d->d_name[0] == 'c' && d->d_name[1] == 'f'); } lpr-2008.05.17.3+nmu1/common_source/startdaemon.c0000644000000000000000000000660511013655775016174 0ustar /* $OpenBSD: startdaemon.c,v 1.12 2007/05/01 16:32:06 stevesk Exp $ */ /* $NetBSD: startdaemon.c,v 1.10 1998/07/18 05:04:39 lukem Exp $ */ /* * 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. 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 #if 0 static const char sccsid[] = "@(#)startdaemon.c 8.2 (Berkeley) 4/17/94"; #else static const char rcsid[] = "$OpenBSD: startdaemon.c,v 1.12 2007/05/01 16:32:06 stevesk Exp $"; #endif #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include "lp.h" #include "pathnames.h" /* * Tell the printer daemon that there are new files in the spool directory. */ int startdaemon(char *printer) { struct sockaddr_un un; int s; size_t n; char buf[BUFSIZ]; s = socket(AF_LOCAL, SOCK_STREAM, 0); if (s < 0) { warn("socket"); return(0); } memset(&un, 0, sizeof(un)); un.sun_family = AF_LOCAL; strlcpy(un.sun_path, _PATH_SOCKETNAME, sizeof(un.sun_path)); siginterrupt(SIGINT, 1); PRIV_START; if (connect(s, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) { if (errno == EINTR && gotintr) { PRIV_END; siginterrupt(SIGINT, 0); close(s); return(0); } PRIV_END; siginterrupt(SIGINT, 0); warn("connect"); fprintf(stderr, "Is lpd daemon running?\n" ); (void)close(s); return(0); } PRIV_END; siginterrupt(SIGINT, 0); if ((n = snprintf(buf, sizeof(buf), "\1%s\n", printer)) >= sizeof(buf) || n == -1) { close(s); return (0); } /* XXX atomicio inside siginterrupt? */ if (write(s, buf, n) != n) { warn("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); } lpr-2008.05.17.3+nmu1/common_source/strlcat.c0000644000000000000000000000322311014357143015305 0ustar /* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ size_t strlcat(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return(dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return(dlen + (s - src)); /* count does not include NUL */ } lpr-2008.05.17.3+nmu1/common_source/strlcpy.c0000644000000000000000000000303111014357152015326 0ustar /* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0) { while (--n != 0) { if ((*d++ = *s++) == '\0') break; } } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ } lpr-2008.05.17.3+nmu1/common_source/vis.c0000644000000000000000000001251411014357114014433 0ustar /* $OpenBSD: vis.c,v 1.19 2005/09/01 17:15:49 millert Exp $ */ /*- * 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. 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. */ #include #include #include #include #include #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') #define isvisible(c) \ (((u_int)(c) <= UCHAR_MAX && isascii((u_char)(c)) && \ (((c) != '*' && (c) != '?' && (c) != '[' && (c) != '#') || \ (flag & VIS_GLOB) == 0) && isgraph((u_char)(c))) || \ ((flag & VIS_SP) == 0 && (c) == ' ') || \ ((flag & VIS_TAB) == 0 && (c) == '\t') || \ ((flag & VIS_NL) == 0 && (c) == '\n') || \ ((flag & VIS_SAFE) && ((c) == '\b' || \ (c) == '\007' || (c) == '\r' || \ isgraph((u_char)(c))))) /* * vis - visually encode characters */ char * vis(char *dst, int c, int flag, int nextc) { if (isvisible(c)) { *dst++ = c; if (c == '\\' && (flag & VIS_NOSLASH) == 0) *dst++ = '\\'; *dst = '\0'; return (dst); } if (flag & VIS_CSTYLE) { switch(c) { case '\n': *dst++ = '\\'; *dst++ = 'n'; goto done; case '\r': *dst++ = '\\'; *dst++ = 'r'; goto done; case '\b': *dst++ = '\\'; *dst++ = 'b'; goto done; case '\a': *dst++ = '\\'; *dst++ = 'a'; goto done; case '\v': *dst++ = '\\'; *dst++ = 'v'; goto done; case '\t': *dst++ = '\\'; *dst++ = 't'; goto done; case '\f': *dst++ = '\\'; *dst++ = 'f'; goto done; case ' ': *dst++ = '\\'; *dst++ = 's'; goto done; case '\0': *dst++ = '\\'; *dst++ = '0'; if (isoctal(nextc)) { *dst++ = '0'; *dst++ = '0'; } goto done; } } if (((c & 0177) == ' ') || (flag & VIS_OCTAL) || ((flag & VIS_GLOB) && (c == '*' || c == '?' || c == '[' || c == '#'))) { *dst++ = '\\'; *dst++ = ((u_char)c >> 6 & 07) + '0'; *dst++ = ((u_char)c >> 3 & 07) + '0'; *dst++ = ((u_char)c & 07) + '0'; goto done; } if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; if (c & 0200) { c &= 0177; *dst++ = 'M'; } if (iscntrl((u_char)c)) { *dst++ = '^'; if (c == 0177) *dst++ = '?'; else *dst++ = c + '@'; } else { *dst++ = '-'; *dst++ = c; } done: *dst = '\0'; return (dst); } /* * strvis, strnvis, strvisx - visually encode characters from src into dst * * Dst must be 4 times the size of src to account for possible * expansion. The length of dst, not including the trailing NULL, * is returned. * * Strnvis will write no more than siz-1 bytes (and will NULL terminate). * The number of bytes needed to fully encode the string is returned. * * Strvisx encodes exactly len bytes from src into dst. * This is useful for encoding a block of data. */ int strvis(char *dst, const char *src, int flag) { char c; char *start; for (start = dst; (c = *src);) dst = vis(dst, c, flag, *++src); *dst = '\0'; return (dst - start); } int strnvis(char *dst, const char *src, size_t siz, int flag) { char *start, *end; char tbuf[5]; int c, i; i = 0; for (start = dst, end = start + siz - 1; (c = *src) && dst < end; ) { if (isvisible(c)) { i = 1; *dst++ = c; if (c == '\\' && (flag & VIS_NOSLASH) == 0) { /* need space for the extra '\\' */ if (dst < end) *dst++ = '\\'; else { dst--; i = 2; break; } } src++; } else { i = vis(tbuf, c, flag, *++src) - tbuf; if (dst + i <= end) { memcpy(dst, tbuf, i); dst += i; } else { src--; break; } } } if (siz > 0) *dst = '\0'; if (dst + i > end) { /* adjust return value for truncation */ while ((c = *src)) dst += vis(tbuf, c, flag, *++src) - tbuf; } return (dst - start); } int strvisx(char *dst, const char *src, size_t len, int flag) { char c; char *start; for (start = dst; len > 1; len--) { c = *src; dst = vis(dst, c, flag, *++src); } if (len) dst = vis(dst, *src, flag, '\0'); *dst = '\0'; return (dst - start); } lpr-2008.05.17.3+nmu1/common_source/vis.h0000644000000000000000000000643111014357070014442 0ustar /* $OpenBSD: vis.h,v 1.11 2005/08/09 19:38:31 millert Exp $ */ /* $NetBSD: vis.h,v 1.4 1994/10/26 00:56:41 cgd Exp $ */ /*- * Copyright (c) 1990 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. 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. * * @(#)vis.h 5.9 (Berkeley) 4/3/91 */ #ifndef _VIS_H_ #define _VIS_H_ /* * to select alternate encoding format */ #define VIS_OCTAL 0x01 /* use octal \ddd format */ #define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropriate */ /* * to alter set of characters encoded (default is to encode all * non-graphic except space, tab, and newline). */ #define VIS_SP 0x04 /* also encode space */ #define VIS_TAB 0x08 /* also encode tab */ #define VIS_NL 0x10 /* also encode newline */ #define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL) #define VIS_SAFE 0x20 /* only encode "unsafe" characters */ /* * other */ #define VIS_NOSLASH 0x40 /* inhibit printing '\' */ #define VIS_GLOB 0x100 /* encode glob(3) magics and '#' */ /* * unvis return codes */ #define UNVIS_VALID 1 /* character valid */ #define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */ #define UNVIS_NOCHAR 3 /* valid sequence, no character produced */ #define UNVIS_SYNBAD -1 /* unrecognized escape sequence */ #define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */ /* * unvis flags */ #define UNVIS_END 1 /* no more characters */ #include __BEGIN_DECLS char *vis(char *, int, int, int); int strvis(char *, const char *, int); int strnvis(char *, const char *, size_t, int) __attribute__ ((__bounded__(__string__,1,3))); int strvisx(char *, const char *, size_t, int) __attribute__ ((__bounded__(__string__,1,3))); int strunvis(char *, const char *); int unvis(char *, char, int *, int); ssize_t strnunvis(char *, const char *, size_t) __attribute__ ((__bounded__(__string__,1,3))); __END_DECLS #endif /* !_VIS_H_ */ lpr-2008.05.17.3+nmu1/debian/0000755000000000000000000000000014156575106012052 5ustar lpr-2008.05.17.3+nmu1/debian/NEWS.Debian0000644000000000000000000000062310176611664013731 0ustar lpr (1:2003.09.23-3) unstable; urgency=low * By default, lpd will no longer listen to the TCP printer port by default. To change this, you must edit the /etc/default/lpd file and remove the -s option. You only need lpd to listen over TCP port only if you need to accept connections from remote clients. Printing to remote print servers and local printing does not require this. lpr-2008.05.17.3+nmu1/debian/README.Debian0000644000000000000000000000207111014417332014075 0ustar lpr for Debian ---------------------- Please note that as of version 2000.05.07-1, Debian is now using OpenBSD lpr as the upstream source. This means that, as in the old days, filters are not run for remote printers. An up to date source code is available on http://git.debian.org/?p=collab-maint/lpr.git;a=summary Configuration -------------------- For quick and painless configuration, install package magicfilter, and configure the printer using its `/usr/sbin/magicfilterconfig` utility to have your printer working in less than a minute. People that want to know how lpr works, read on. Printer configuration is done in the /etc/printcap file. For detailed information, please see man 5 printcap. For an overview of the BSD lpr print spooler, see the UNIX System Manager's Manual which is available http://people.debian.org/~adamm/doc/#smm Section 7 deals with the printer spooler. Please note that this manual is not specific to Debian or Linux and it is a little bit out of date. Manual pages for all of the utilities supersede any information in these guides. lpr-2008.05.17.3+nmu1/debian/changelog0000644000000000000000000002662514156575106013737 0ustar lpr (1:2008.05.17.3+nmu1) unstable; urgency=medium * Non-maintainer upload. * add build-arch and build-indep targets to debian/rules (Closes: #999216) -- Damyan Ivanov Thu, 16 Dec 2021 08:35:18 +0000 lpr (1:2008.05.17.3) unstable; urgency=medium * Non-maintainer upload. * Fix FTBFS with glibc 2.28. (Closes: #916148) * Sugggest ghostscript instead of gs. (Closes: #601355) * Build with -g to get non-empty -dbgsym. -- Adrian Bunk Fri, 11 Jan 2019 22:06:54 +0200 lpr (1:2008.05.17.2) unstable; urgency=medium * Non-maintainer upload. * Move to debhelper compat level 9. (Closes: #817569) -- Chris Lamb Sun, 25 Sep 2016 15:08:29 +0200 lpr (1:2008.05.17.1) unstable; urgency=medium * Acknowledge NMU. Thank you. (closes: #544552) * Fix an integer overflow in chksize() function on systems with > 1TB spool partition. (closes: #769925) -- Adam Majer Thu, 20 Nov 2014 21:33:12 -0600 lpr (1:2008.05.17+nmu1) unstable; urgency=low * Non-maintainer upload to fix a 1.5 years old pending bug. * Apply patch from Petr Salinger to fix the build on GNU/kFreeBSD (closes: #544552). -- Aurelien Jarno Fri, 22 Apr 2011 16:21:15 +0200 lpr (1:2008.05.17) unstable; urgency=low * Change package priority from standard to optional since it was already done in the override file * Add upstream revision file * Upgrade standards to 3.7.3 * Overwrite logcheck-database provided logcheck file with our own version (closes: #418393) * Added upstream patches + lpd/printjob.c [rev. 1.41] - rfc 3834 support: "Auto-Submitted: auto-generated" on lots of things; from Tamas TEVESZ + Synched to upstream lpr as of 2008-05-17 * Merged logcheck-database rule with the ones provided by lpr. * Remove old changelog entries for versions before OpenBSD's version was used as an upstream. * Added Vcs- info to control file. -- Adam Majer Mon, 19 May 2008 21:11:19 -0500 lpr (1:2006.11.04) unstable; urgency=low * Added upstream patches + lpr.c [rev. 1.39] - portability patch s/0/SEEK_SET/ in lseek * /var/log/lp-{acct,errs} are now rotated weekly with lp:adm ownership with 0640 permissions. The latter is to counteract any security related information being leaked from filter's stderr to the log to the user. (closes: #390720) -- Adam Majer Sat, 4 Nov 2006 23:21:59 -0600 lpr (1:2006.08.03) unstable; urgency=low * Fixed the changelog errors (closes: #307753) * (lpd/lpd.8) Manpage update clarifying that lpd will silently drop print requests if reverse DNS lookup fails. * Remove /etc/printcap conffile on purge only if it was not modified (closes: #326046) * Added a slightly modified patch to enable lpd to recognize hosts.equiv and hosts.lpd lines without trailing newline (closes: #323063) * Applied a patch from Martin Michlmayr that moves the dot in the init script next to the lpd name. This is to make the init script consistent with the other deamon's init scrips. (closes: #337222) * Plug a memory leak in displayq.c when nitems==0. Patch from OpenBSD cvs - originally from NetBSD. * Fixed lprm to function correctly when the - parameters is used. (closes: #337743) * Added LSB formatted dependencies to the init script (closes: #376960) * Updated Standards to 3.7.2. No changes. -- Adam Majer Thu, 3 Aug 2006 18:12:19 -0500 lpr (1:2005.05.01) unstable; urgency=low * Changed to Debian native package. It is still based from OpenBSD cvs, but syncing with upstream now occurs on an ongoing basis. * (lpd/printjob.c) Applied a slightly modified patch from upstream to pstatus which could cause possible stack corruption if vnsprintf failed. -- Adam Majer Sun, 1 May 2005 17:56:18 -0500 lpr (1:2005.01.28-5) unstable; urgency=low * Fix a FTBFS - logcheck is not present as a group. Use dh_installlogcheck -- Adam Majer Wed, 13 Apr 2005 02:14:04 -0500 lpr (1:2005.01.28-4) unstable; urgency=low * Added logcheck ignore files for server configuration. * Added a patch from upstream that fixes handling of command line options for lpr (lpr.c 1.37 revision upstream) * Using dpatch for upstream patches which should keep things easier to sync when upstream is synced. -- Adam Majer Tue, 12 Apr 2005 18:31:45 -0500 lpr (1:2005.01.28-3) unstable; urgency=low * Added a timeout to question in postrm regarding removal the spool directory during purge. Timeout is needed to handle non-interactive removals. (closes: #293308) * Added a hint (daemon not running) to error condition when connection to daemon fails. (closes: #180287) -- Adam Majer Thu, 17 Feb 2005 12:35:59 -0600 lpr (1:2005.01.28-2) unstable; urgency=low * Apply patch from Junio Hamano that makes the rotated log uid=lp instead of root (closes: #283172) * Apply a patch from NIIBE Yutaka to make cross-compile easier (closes: #286618) -- Adam Majer Mon, 31 Jan 2005 11:49:41 -0600 lpr (1:2005.01.28-1) unstable; urgency=low * Sync to new upstream version - adds -j option to specify job name - fixes banner printing * Remove extraneous $i from postinst -- Adam Majer Sun, 30 Jan 2005 08:01:11 -0500 lpr (1:2003.09.23-7) unstable; urgency=high * Remove bash specific syntax in postinst. To make sure permissions are fixed for the new lpr, rerun permission fixups on /var/spool/lpd/*, again. (closes: #261590) -- Adam Majer Tue, 27 Jul 2004 16:45:19 -0500 lpr (1:2003.09.23-6) unstable; urgency=low * Fixed a possible null deference in checkremote() (closes: #258539) * Added date listing in the printout of `lpq -l` (closes: #155053) * If bind to a socket fails (busy), waits for up to 35 seconds before giving up on it * Fetches the numeric uid of UID(lp) instead of relying that it is always 7 (closes: #258478) -- Adam Majer Tue, 13 Jul 2004 14:14:39 -0500 lpr (1:2003.09.23-5) unstable; urgency=low * Added __ivaliduser_sa from OpenBSD so that hosts.lpd can again include IP addresses (closes: #85133) This should also re-enable netgroup support in both, hosts.equiv and hosts.lpd (closes: #70521) Also seems to fix printing over IPv6 sockets :) * debian/postinst: + Updat permissions of the .seq files in the spool directories (closes: #258478) -- Adam Majer Sat, 10 Jul 2004 15:36:14 -0500 lpr (1:2003.09.23-4) unstable; urgency=low * Quiet postinst a bit. -- Adam Majer Sun, 4 Jul 2004 20:25:53 -0500 lpr (1:2003.09.23-3) unstable; urgency=low * debian/postinst: `chown` now uses : not . (closes: #256984) * debian/printcap.5: "new" upstream version * lpr/lpr.c: + Fixed some nasty getopt parsing bugs + pr(1) filter (lpr -p) now uses form-feed to get to new page. * lpd/printjob.c: + Fixed banner printing by adding \r * Added /etc/default/lpd file that controls startup options of lpr. By default, lpr will no longer listen on TCP port. You may choose to re-enable this if you need to accept print requests over the network. * Fixed upgrade from pre-1:2003.09.23 version of lpr * Added some configuration notes in README.Debian (closes: #180274) -- Adam Majer Sun, 4 Jul 2004 14:51:06 -0500 lpr (1:2003.09.23-2) unstable; urgency=low * Applied patch to fix -s option thanks to Joachim H. Kaiser (closes: #214445) * Fixed a bug in lpd/lpd.c where lines with whitespace in hosts.{lpd,equiv} were treated as EOF instead of being ignored * Added filter's path to the logged error message when input filter dies. (closes: #138367) * Fixed a bug introduced in porting from OpenBSD in common_source/displaq.c by adding vis.c fetched from latest OpenBSD source (closes: #255852) * Fixed a locking problem where multiple printjobs (one for each printjob) were launched simultaneously. lpr now uses flock() for locking instead of OpenBSD's O_EXLOCK in open(). * Fixed cron.weekly to no longer start the daemon if it is not running (closes: #142115) -- Adam Majer Thu, 24 Jun 2004 19:34:10 -0500 lpr (1:2003.09.23-1) unstable; urgency=low * Upload of IPv6 capable lpr to Sid. Note that you'll need a relatively new kernel, like debian 2.4.24 kernel, to listen on IPv6 socket. * Change the ownership of all the files in the spool directory /var/spool/lpd to lp.lp in the postinst. * Added a lock file to /var/spool/lpd as required by the FHS (closes: #228542) * New init script thanks to Ryan VanMiddlesworth should clean up all lpd processes, not just one. (closes: #56359) -- Adam Majer Sun, 20 Jun 2004 18:43:22 -0500 lpr (1:2003.09.23-0test1) experimental; urgency=low * New upstream release (sync with CVS on 2003-09-23) - you may need to change permissions of files in the spool directory to 'lp' from 'root'. * Removed build-depends on pmake - lpr will now use GNU make -- Adam Majer Tue, 4 Nov 2003 08:06:38 -0600 lpr (1:2000.05.07-5) unstable; urgency=low * New maintainer (closes: #182928) * Acknowledge some NMUs (closes: #116728, #103562, #112523, #186478) * Updated standards to 3.6.1 -- Adam Majer Wed, 24 Sep 2003 02:32:42 -0500 lpr (1:2000.05.07-4.20) unstable; urgency=high * Non-maintainer upload by the Security Team * Rebuilt for sid so the update for woody can enter the archive -- Martin Schulze Thu, 20 Mar 2003 20:03:29 +0100 lpr (1:2000.05.07-4.3) stable-security; urgency=high * Non-maintainer upload by the Security Team * Applied patch from SuSE to fix buffer overvlow and arbitrary file access -- Martin Schulze Sat, 15 Mar 2003 14:54:38 +0100 lpr (1:2000.05.07-4.2) unstable; urgency=low * NMU * Fix lpr -# handling (closes: #103562, #112523) -- Julian Gilbey Thu, 21 Mar 2002 15:14:38 +0000 lpr (1:2000.05.07-4.1) unstable; urgency=low * NMU * handle non-tty remove's, patch in bts. Closes: #116728. -- LaMont Jones Mon, 11 Mar 2002 11:37:43 -0700 lpr (1:2000.05.07-4) unstable; urgency=low * Reverted to mktemp() for now, because for some inexplicable reason I didn't notice that mkstemp() isn't a drop-in replacement -- Adam Klein Thu, 18 Jan 2001 20:40:53 -0800 lpr (1:2000.05.07-3) unstable; urgency=low * Applied patch from Matt Zimmerman to have lpd itself parse hosts.{equiv,lpd} instead of using an internal glibc function (closes: #67044) * Modified lpr to use getopt() (closes: #51157) * Removed suidmanager use * Removed potato build stuff from rules * Use mkstemp() in place of mktemp() in printjob.c * Moved the master lockfile back to /var/run/lpd.pid for the Nth time (closes: #80486) -- Adam Klein Mon, 15 Jan 2001 15:17:34 -0800 lpr (1:2000.05.07-2) unstable; urgency=low * Got rid of duplicate fclose()s in getcap.c (closes: #64199, #63929) -- Adam Klein Tue, 16 May 2000 23:15:24 -0700 lpr (1:2000.05.07-1) unstable; urgency=low * Now using OpenBSD as upstream source (may close many bugs) -- Adam Klein Sun, 7 May 2000 21:40:41 -0700 lpr-2008.05.17.3+nmu1/debian/compat0000644000000000000000000000000212771746115013251 0ustar 9 lpr-2008.05.17.3+nmu1/debian/control0000644000000000000000000000140613416173536013455 0ustar Source: lpr Section: net Priority: optional Build-Depends: debhelper (>= 9) Maintainer: Adam Majer Standards-Version: 3.7.3 Vcs-Browser: http://git.debian.org/?p=collab-maint/lpr.git;a=summary Vcs-Git: git://git.debian.org/git/collab-maint/lpr.git Package: lpr Architecture: any Depends: ${shlibs:Depends}, netbase Suggests: magicfilter | apsfilter, ghostscript Conflicts: suidmanager (<< 0.50) Replaces: logcheck-database Description: BSD lpr/lpd line printer spooling system This is the BSD printer spooler and associated utilities. You can use this for local and remote printers. . If you install magicfilter or apsfilter (along with ghostscript), lpr will be able to automatically handle special file types (such as Postscript and PDF files). lpr-2008.05.17.3+nmu1/debian/copyright0000644000000000000000000000111210176611664013776 0ustar This is Debian GNU/Linux's prepackaged version of lpr, the BSD line printing spool system. This package is maintained by Adam Klein . This version of lpr is taken from OpenBSD, and was obtained via CVS from anoncvs.usa.openbsd.org. It also includes, from OpenBSD, the getcap.c file, which is part of the OpenBSD C library. It has been edited to remove its dependency on libdb. The printcap.5 manpage is also from them. The lpr package is distributed under the BSD licence. On Debian systems this licence is available in the file /usr/share/common-licenses/BSD. lpr-2008.05.17.3+nmu1/debian/cron.weekly0000644000000000000000000000056410523271050014223 0ustar #! /bin/sh DAEMON=/usr/sbin/lpd # Make sure the lpr package is installed (use pac because lprng doesn't have it test -f /usr/sbin/pac || exit 0 savelog -u lp -g adm -m 0640 -n -q -t /var/log/lp-acct savelog -u lp -g adm -m 0640 -n -q -t /var/log/lp-errs if /sbin/start-stop-daemon --quiet --stop --signal 0 --exec $DAEMON; then /etc/init.d/lpd restart >/dev/null fi lpr-2008.05.17.3+nmu1/debian/dirs0000644000000000000000000000023110222430053012707 0ustar etc etc/logcheck/ignore.d.server usr/sbin usr/bin usr/share/man/man1 usr/share/man/man5 usr/share/man/man8 var/log var/spool/lpd/lp var/spool/lpd/remote lpr-2008.05.17.3+nmu1/debian/examples0000644000000000000000000000002010176611664013601 0ustar debian/printcap lpr-2008.05.17.3+nmu1/debian/install0000644000000000000000000000022510176611664013440 0ustar lpr/lpr usr/bin lpq/lpq usr/bin lprm/lprm usr/bin lpc/lpc usr/sbin lpd/lpd usr/sbin filters/lpf usr/sbin pac/pac usr/sbin lptest/lptest usr/bin lpr-2008.05.17.3+nmu1/debian/lpd.default0000644000000000000000000000037110176611664014176 0ustar ## Options used by the lpd daemom. Default is to disable ## TCP/IP socket ## ## (see `man lpd` for more options) ## -s - does not listen on any TCP/IP addresses ## -b - listens to a specific IP address only # # OPTIONS= OPTIONS="-s" lpr-2008.05.17.3+nmu1/debian/lpd.init0000644000000000000000000000226110464477230013514 0ustar #!/bin/sh # ### BEGIN INIT INFO # Provides: lpd # Required-Start: $syslog # Required-Stop: $syslog # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: BSD lpr/lpd line printer spooling system # Description: This is the BSD printer spooler and associated # utilities. You can use this for local and remote # printers. ### END INIT INFO PATH=/bin:/usr/bin:/sbin:/usr/sbin DAEMON=/usr/sbin/lpd OPTIONS="" . /etc/default/lpd test -x $DAEMON -a -f /usr/sbin/pac || exit 0 case "$1" in start) echo -n "Starting printer spooler: lpd" if start-stop-daemon --quiet --stop --signal 0 --exec $DAEMON then echo " [already running]" else /sbin/start-stop-daemon --start --quiet --exec $DAEMON -- $OPTIONS echo "." fi ;; stop) echo -n "Stopping printer spooler: lpd" if start-stop-daemon --quiet --stop --signal 0 --exec $DAEMON then start-stop-daemon --quiet --stop --exec $DAEMON echo "." else echo " [not running]"; fi ;; force-reload|restart) $0 stop sleep 1 $0 start ;; *) echo "Usage: /etc/init.d/lpd {start|stop|restart|force-reload}" exit 1 esac exit 0 lpr-2008.05.17.3+nmu1/debian/lpr.logcheck.ignore.server0000644000000000000000000000041510767525356017145 0ustar ^\w{3} [ :0-9]{11} [\._[:alnum:]]+ lpd\[[0-9]+\]: [\._[:alnum:]]+ requests displayq (short|long) [[:alnum:]]+$ ^\w{3} [ :0-9]{11} [\._[:alnum:]]+ lpd\[[0-9]+\]: [\._[:alnum:]]+ requests recvjob [[:alnum:]]+$ ^\w{3} [ :0-9]{11} [\._[:alnum:]]+ lpd\[[0-9]+\]: restarted$ lpr-2008.05.17.3+nmu1/debian/lpr.postrm0000644000000000000000000000035010464472014014103 0ustar #!/bin/sh # Remove /etc/printcap file on purge ONLY if it has not changed. if [ "x$1" = "xpurge" ] ; then cmp -s /etc/printcap /usr/share/doc/lpr/examples/printcap if [ $? -eq 0 ] ; then rm -f /etc/printcap fi fi #DEBHELPER# lpr-2008.05.17.3+nmu1/debian/manpages0000644000000000000000000000015610176611664013570 0ustar lpq/lpq.1 lptest/lptest.1 lprm/lprm.1 lpr/lpr.1 filters/lpf.8 pac/pac.8 lpc/lpc.8 lpd/lpd.8 debian/printcap.5 lpr-2008.05.17.3+nmu1/debian/postinst0000644000000000000000000000202211014416144013636 0ustar #!/bin/sh if [ ! -e /etc/printcap ]; then cp /usr/share/doc/lpr/examples/printcap /etc/ fi for i in /var/log/lp-acct /var/log/lp-errs do if [ ! -f $i ]; then touch $i chmod 644 $i fi done # Fix permissions - everything needs to be lp.lp now since lpd drop priv. all over the place # We also fix permissions if any file in spool is not owned by lp:lp OR the lead spool # diretory does not have 2775 permissions. if [ "$2" != "" ] && dpkg --compare-versions "$2" lt 1:2003.09.23-7; then echo -n "Updating /var/spool/lpd permissions " chmod -f 2775 /var/spool/lpd chmod -f 2775 /var/spool/lpd/lp chmod -f 2775 /var/spool/lpd/remote chown -f lp:lp --recursive /var/spool/lpd chmod -f 640 `find /var/spool/lpd | grep /lock$` 2> /dev/null chmod -f 661 `find /var/spool/lpd | grep /.seq$` 2> /dev/null chown -f lp:lp `find /var/spool/lpd | grep /.seq$` 2> /dev/null echo "[done]" fi if [ -x /usr/sbin/update-mime -a "$1" = configure ] && dpkg --compare-versions "$2" lt 1:0.35-3; then update-mime fi #DEBHELPER# lpr-2008.05.17.3+nmu1/debian/postrm0000644000000000000000000000053610201054575013312 0ustar #!/bin/bash set -e if [ $1 = "purge" ] then rm -f /var/log/lp-acct* /var/log/lp-errs* echo -n "Do you want to remove /var/spool/lpd? [y/N] " if ! read -t 30 X; then # added to handle EOF on stdin gracefully as well as non-interactive removals X="n" fi if [ "$X" = Y -o "$X" = y ]; then rm -rf /var/spool/lpd fi fi #DEBHELPER# lpr-2008.05.17.3+nmu1/debian/preinst0000644000000000000000000000021410176611664013454 0ustar #!/bin/sh set -e if [ -x /usr/sbin/lpd ]; then start-stop-daemon --stop --quiet --oknodo --name lpd --exec /usr/sbin/lpd fi #DEBHELPER# lpr-2008.05.17.3+nmu1/debian/printcap0000644000000000000000000000120310176611664013607 0ustar # /etc/printcap: printer capability database. See printcap(5). # You can use the filter entries df, tf, cf, gf etc. for # your own filters. See /etc/filter.ps, /etc/filter.pcl and # the printcap(5) manual page for further details. lp|Generic dot-matrix printer entry:\ :lp=/dev/lp0:\ :sd=/var/spool/lpd/lp:\ :af=/var/log/lp-acct:\ :lf=/var/log/lp-errs:\ :pl#66:\ :pw#80:\ :pc#150:\ :mx#0:\ :sh: # rlp|Remote printer entry:\ # :lp=:\ # :rm=remotehost:\ # :rp=remoteprinter:\ # :sd=/var/spool/lpd/remote:\ # :mx#0:\ # :sh: lpr-2008.05.17.3+nmu1/debian/printcap.50000644000000000000000000001757210176611664013772 0ustar .\" $OpenBSD: printcap.5,v 1.17 2003/06/02 23:30:14 millert Exp $ .\" $NetBSD: printcap.5,v 1.7 1998/02/20 12:24:50 hubertf Exp $ .\" .\" 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. 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. .\" .\" @(#)printcap.5 8.2 (Berkeley) 12/11/93 .\" .Dd December 11, 1993 .Dt PRINTCAP 5 .Os .Sh NAME .Nm printcap .Nd printer capability database .Sh SYNOPSIS .Nm printcap .Sh DESCRIPTION The .Nm file is a simplified version of the .Xr termcap 5 database used to describe line printers. The spooling system accesses the .Nm file every time it is used, allowing dynamic addition and deletion of printers. Each entry in the database is used to describe one printer. This database may not be substituted for, as is possible for .Xr termcap 5 , because it may allow accounting to be bypassed. .Pp The default printer is normally .Dq lp , though the environment variable .Ev PRINTER may be used to override this. Each spooling utility supports an option, .Fl P Ns Ar printer , to allow explicit naming of a destination printer. .Pp Refer to the .%T "4.3 BSD Line Printer Spooler Manual" for a complete discussion on how to set up the database for a given printer. .Sh CAPABILITIES Refer to .Xr termcap 5 for a description of the file layout. .Bl -column "xx" "xx" "/var/spool/" .Sy Name Type Default Description .It "af str" Ta Dv NULL Ta No "name of accounting file" .It "br num none if lp is a tty, set baud rate" .Pf ( Xr ioctl 2 call) .It "cf str" Ta Dv NULL Ta No "cifplot data filter" .It "df str" Ta Dv NULL Ta No "tex data filter" .Pf ( Tn DVI format) .It "fc num 0 if lp is a tty, clear flag bits" .Pq Aq Pa sgtty.h .It "ff str" Ta So Li \ef Sc Ta No "string to send for a form feed" .It "fo bool false print a form feed when device is opened" .It "fs num 0 if lp is a tty, set flag bits" .Pq Aq Pa sgtty.h .It "gf str" Ta Dv NULL Ta No "graph data filter" .Pf ( Xr plot 3 format) .It "hl bool false print the burst header page last" .It "ic bool false supports non-standard ioctl to indent printout" .It "if str" Ta Dv NULL Ta No "name of text filter which does accounting" .It "lf str" Ta Pa /dev/console Ta No "error logging file name" .It "lo str" Ta Pa lock Ta No "name of lock file" .It "lp str" Ta Pa /dev/lp Ta No "local printer device, or port@host for remote" .It "ms str" Ta Dv NULL Ta No "list of terminal modes to set or clear" .It "mx num 1000 max file size (in" .Dv BUFSIZ blocks); 0=unlimited .It "nd str" Ta Dv NULL Ta No "next directory for queues list (unimplemented)" .It "nf str" Ta Dv NULL Ta No "ditroff data filter (device independent troff)" .It "of str" Ta Dv NULL Ta No "name of output filtering program" .It "pc num 200 price per foot or page in hundredths of cents" .It "pl num 66 page length (in lines)" .It "pw num 132 page width (in characters)" .It "px num 0 page width in pixels (horizontal)" .It "py num 0 page length in pixels (vertical)" .It "rf str" Ta Dv NULL Ta No "filter for printing" .Tn FORTRAN style text files .It "rg str" Ta Dv NULL Ta No "restricted group-only group members can access" .It "rm str" Ta Dv NULL Ta No "machine name for remote printer" .It "rp str ``lp'' remote printer name argument" .It "rs bool false remote users must have a local account" .It "rw bool false open printer device for reading and writing" .It "sb bool false short banner (one line only)" .It "sc bool false suppress multiple copies" .It "sd str" Ta Pa /var/spool/lpd Ta No "spool directory" .It "sf bool false suppress form feeds" .It "sh bool false suppress printing of burst page header" .It "st str" Ta Pa status Ta No "status file name" .It "tf str" Ta Dv NULL Ta No "troff data filter (cat phototypesetter)" .It "tr str" Ta Dv NULL Ta No "trailer string to print when queue empties" .It "vf str" Ta Dv NULL Ta No "raster image filter" .It "xc num 0 if lp is a tty, clear local mode bits" .Pq Xr tty 4 .It "xs num 0 if lp is a tty, set local mode bits" .Pq Xr tty 4 .El .Pp If the local line printer driver supports indentation, the daemon must understand how to invoke it. .Sh FILTERS If a printer is specified via .Sy lp (either local or remote), the .Xr lpd 8 daemon creates a pipeline of .Dq filters to process files for various printer types. The pipeline is not set up for remote printers specified via .Sy rm unless the local host is the same as the remote printer host given. The filters selected depend on the flags passed to .Xr lpr 1 . The pipeline set up is: .Bd -literal -offset indent p pr | if regular text + pr(1) none if regular text c cf cifplot d df DVI (tex) g gf plot(3) n nf ditroff f rf Fortran t tf troff v vf raster image .Ed .Pp The .Sy if filter is invoked with arguments: .Bd -filled -offset indent .Sy if .Op Fl c .Fl w Ns Ar width .Fl l Ns Ar length .Fl i Ns Ar indent .Fl n Ar login .Fl h Ar host acct-file .Ed .Pp The .Fl c flag is passed only if the .Fl l flag (pass control characters literally) is specified to .Xr lpr 1 . .Ar width and .Ar length specify the page width and length (from .Sy pw and .Sy pl , respectively) in characters. The .Fl n and .Fl h parameters specify the login name and host name of the owner of the job, respectively. The .Ar acct-file function is passed from the .Sy af .Nm entry. .Pp If no .Sy if is specified, .Sy of is used instead, with the distinction that .Sy of is opened only once, while .Sy if is opened for every individual job. Thus, .Sy if is better suited to performing accounting. The .Sy of is only given the .Ar width and .Ar length flags. .Pp All other filters are called as: .Bd -filled -offset indent .Nm filter .Fl x Ns Ar width .Fl y Ns Ar length .Fl n Ar login .Fl h Ar host acct-file .Ed .Pp where .Ar width and .Ar length are represented in pixels, specified by the .Sy px and .Sy py entries, respectively. All filters take .Em stdin as the file, .Em stdout as the printer, may log either to .Em stderr or using .Xr syslog 3 , and must not ignore .Dv SIGINT . .Sh LOGGING Error messages generated by the line printer programs themselves are logged by .Xr syslog 3 using the .Dv LPR facility. Messages printed on .Em stderr of one of the filters are sent to the corresponding .Sy lf file. The filters may, of course, use .Xr syslog 3 themselves. .Pp Error messages sent to the console have a carriage return and a line feed appended to them, rather than just a line feed. .Sh SEE ALSO .Xr lpq 1 , .Xr lpr 1 , .Xr lprm 1 , .Xr termcap 5 , .Xr lpc 8 , .Xr lpd 8 , .Xr pac 8 .Rs .%T "4.3 BSD Line Printer Spooler Manual" .Re .Sh HISTORY The .Nm file format appeared in .Bx 4.2 . lpr-2008.05.17.3+nmu1/debian/rules0000755000000000000000000000341714156574677013153 0ustar #!/usr/bin/make -f # Sample debian/rules that uses debhelper. GNU copyright 1997 by Joey Hess. # Modified for lpr by Adam Klein # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 CFLAGS = -Wall -g -O2 -D_GNU_SOURCE -D__KAME__ -I../common_source CPPFLAGS = -Wall -g -O2 -D_GNU_SOURCE -D__KAME__ -I../common_source # -D_BSD_SOURCE build: build-arch build-indep build-arch: build-arch-stamp build-arch-stamp: dh_testdir make -W CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" touch $@ build-indep: # nothing to do here clean: dh_testdir dh_testroot rm -f build-arch-stamp install-stamp -make clean dh_clean install: build dh_testdir dh_testroot dh_clean -k dh_installdirs touch install-stamp # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install dh_testdir dh_testroot dh_install dh_installman dh_installdocs dh_installexamples dh_installlogcheck dh_installinit --name=lpd dh_installcron dh_installchangelogs dh_strip dh_compress dh_fixperms chown root.lp debian/lpr/usr/bin/lpr \ debian/lpr/usr/bin/lpq \ debian/lpr/usr/bin/lprm \ debian/lpr/usr/sbin/lpc chmod 6755 debian/lpr/usr/bin/lpr \ debian/lpr/usr/bin/lpq \ debian/lpr/usr/bin/lprm chmod 2755 debian/lpr/usr/sbin/lpc chown lp.lp debian/lpr/var/spool/lpd \ debian/lpr/var/spool/lpd/lp \ debian/lpr/var/spool/lpd/remote chmod 2775 debian/lpr/var/spool/lpd \ debian/lpr/var/spool/lpd/lp \ debian/lpr/var/spool/lpd/remote dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch .PHONY: build build-arch build-indep clean binary-indep binary-arch binary install lpr-2008.05.17.3+nmu1/filters/0000755000000000000000000000000013416173536012277 5ustar lpr-2008.05.17.3+nmu1/filters/Makefile0000644000000000000000000000026410176611664013740 0ustar # from: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $OpenBSD: Makefile,v 1.2 1997/01/17 16:12:33 millert Exp $ PROG= lpf MAN= lpf.8 SRCS= lpf.c BINDIR= /usr/sbin include ../Makefile.in lpr-2008.05.17.3+nmu1/filters/lpf.80000644000000000000000000000105610176611664013152 0ustar .TH LPF 8 "25 February 1999" BSD "Debian User's Guide" .SH NAME lpf \- lpd filter for nroff output .SH SYNOPSIS lpf -w width -l length .SH DESCRIPTION .B lpf is a filter which reads the output of nroff and converts lines with ^H's to overwritten lines. Thus this works like .BR ul (1) but is much better: it can handle more than 2 overwrites and it is written with some style. .SH NOTES This program was designed long ago, and is not much if any use today. .SH BUGS lpf will send itself the STOP signal when it encounters the character sequence `\\031\\1'. lpr-2008.05.17.3+nmu1/filters/lpf.c0000644000000000000000000001301210176611664013220 0ustar /* $OpenBSD: lpf.c,v 1.11 2004/04/14 20:52:20 millert Exp $ */ /* $NetBSD: lpf.c,v 1.8 2000/04/29 00:12:32 abs Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static const char sccsid[] = "@(#)lpf.c 8.1 (Berkeley) 6/6/93"; #else static const char rcsid[] = "$OpenBSD: lpf.c,v 1.11 2004/04/14 20:52:20 millert Exp $"; #endif #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. */ #include #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 */ int onlcr; /* map nl->cr-nl */ char *name; /* user's login name */ char *host; /* user's machine name */ char *acctfile; /* accounting information file */ void usage(void); int main(int argc, char **argv) { FILE *p = stdin, *o = stdout; int i, col; char *cp; int done, linedone, maxrep, ch; char *limit; while ((ch = getopt(argc, argv, "crh:i:j:l:n:w:")) != -1) { switch (ch) { case 'n': name = optarg; break; case 'h': host = optarg; break; case 'w': if ((i = atoi(optarg)) > 0 && i <= MAXWIDTH) width = i; break; case 'l': length = atoi(optarg); break; case 'i': indent = atoi(optarg); break; case 'r': /* map nl->cr-nl */ onlcr++; break; case 'c': /* Print control chars */ literal++; break; case 'j': /* ignore job name */ break; default: usage(); } } argc -= optind; argv += optind; if (argc) acctfile = *argv; memset(buf, ' ', sizeof(buf)); 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 { if (onlcr) putc('\r', o); 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); } void usage(void) { extern char *__progname; fprintf(stderr, "usage: %s [-c] [-r] [-h host] [-i indent] [-l length]" " [-n name] [-w width] [acctfile]\n", __progname); exit(1); } lpr-2008.05.17.3+nmu1/lpc/0000755000000000000000000000000013416173536011405 5ustar lpr-2008.05.17.3+nmu1/lpc/Makefile0000644000000000000000000000057310176611664013051 0ustar # from: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $OpenBSD: Makefile,v 1.3 2002/05/20 23:13:50 millert Exp $ PROG= lpc CFLAGS+=-I${.CURDIR}/../common_source MAN= lpc.8 SRCS= lpc.c cmds.c cmdtab.c ../common_source/startdaemon.c ../common_source/common.c \ ../common_source/common_vars.c ../common_source/getcap.c BINDIR= /usr/sbin BINGRP= daemon BINMODE=2555 include ../Makefile.in lpr-2008.05.17.3+nmu1/lpc/cmds.c0000644000000000000000000006343111013656726012504 0ustar /* $OpenBSD: cmds.c,v 1.19 2007/04/07 21:57:26 stevesk Exp $ */ /* $NetBSD: cmds.c,v 1.12 1997/10/05 15:12:06 mrg Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static const char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/28/95"; #else static const char rcsid[] = "$OpenBSD: cmds.c,v 1.19 2007/04/07 21:57:26 stevesk Exp $"; #endif #endif /* not lint */ /* * lpc -- line printer control program -- commands: */ #include #include #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(int); static void cleanpr(void); static void disablepr(void); static int doarg(char *); static int doselect(const struct dirent *); static void enablepr(void); static void prstat(void); static void putmsg(int, char **); static int sortq(const void *, const void *); static void startpr(int); static void stoppr(void); static int touch(struct queue *); static void unlinkf(char *); static void upstat(char *); /* * kill an existing daemon and disable printing. */ void doabort(int argc, char **argv) { int c, status; char *cp1, *cp2; char prbuf[100]; if (argc == 1) { printf("Usage: abort {all | printer ...}\n"); return; } if (argc == 2 && strcmp(argv[1], "all") == 0) { printer = prbuf; while (cgetnext(&bp, printcapdb) > 0) { cp1 = prbuf; cp2 = bp; while ((c = *cp2++) && c != '|' && c != ':' && (cp1 - prbuf) < sizeof(prbuf) - 1) *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(int dis) { 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)snprintf(line, sizeof(line), "%s/%s", SD, LO); printf("%s:\n", printer); PRIV_START; /* * Turn on the owner execute bit of the lock file to disable printing. */ if (dis) { if (stat(line, &stbuf) >= 0) { stbuf.st_mode |= S_IXUSR; if (chmod(line, stbuf.st_mode & 0777) < 0) printf("\tcannot disable printing\n"); else { upstat("printing disabled\n"); printf("\tprinting disabled\n"); } } else if (errno == ENOENT) { if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0760)) < 0) printf("\tcannot create lock file\n"); else { (void)fchown(fd, DEFNUID, -1); (void)close(fd); upstat("printing disabled\n"); printf("\tprinting disabled\n"); printf("\tno daemon to abort\n"); } goto out; } else { printf("\tcannot stat lock file\n"); goto out; } } /* * Kill the current daemon to stop printing now. */ fd = safe_open(line, O_RDONLY|O_NOFOLLOW, 0); if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) { if (fd >= 0) close(fd); printf("\tcannot open lock file\n"); goto out; } if (!getcfline(fp) || flock(fileno(fp), LOCK_SH|LOCK_NB) == 0) { (void)fclose(fp); /* unlocks as well */ printf("\tno daemon to abort\n"); goto out; } (void)fclose(fp); if (kill(pid = atoi(line), SIGTERM) < 0) { if (errno == ESRCH) printf("\tno daemon to abort\n"); else printf("\tWarning: daemon (pid %d) not killed\n", pid); } else printf("\tdaemon (pid %d) killed\n", pid); out: PRIV_END; } /* * Write a message into the status file (assumes PRIV_START already called) */ static void upstat(char *msg) { int fd; char statfile[MAXPATHLEN]; if (cgetstr(bp, "st", &ST) == -1) ST = DEFSTAT; (void)snprintf(statfile, sizeof(statfile), "%s/%s", SD, ST); fd = safe_open(statfile, O_WRONLY|O_CREAT|O_NOFOLLOW, 0660); if (fd < 0 || flock(fd, LOCK_EX) < 0) { printf("\tcannot create status file\n"); return; } (void)fchown(fd, DEFNUID, -1); (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(int argc, char **argv) { int c, status; char *cp1, *cp2; char prbuf[100]; if (argc == 1) { printf("Usage: clean {all | printer ...}\n"); return; } if (argc == 2 && strcmp(argv[1], "all") == 0) { printer = prbuf; while (cgetnext(&bp, printcapdb) > 0) { cp1 = prbuf; cp2 = bp; while ((c = *cp2++) && c != '|' && c != ':' && (cp1 - prbuf) < sizeof(prbuf) - 1) *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(const 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(const void *a, const void *b) { const struct dirent **d1, **d2; int c1, c2; d1 = (const struct dirent **)a; d2 = (const struct dirent **)b; if ((c1 = strcmp((*d1)->d_name + 3, (*d2)->d_name + 3)) != 0) 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(void) { int i, n; char *cp, *cp1, *lp; struct dirent **queue; int nitems; if (cgetstr(bp, "sd", &SD) == -1) SD = _PATH_DEFSPOOL; printf("%s:\n", printer); /* XXX depends on SD being non-NUL */ for (lp = line, cp = SD; (lp - line) < sizeof(line) && (*lp++ = *cp++) != '\0'; ) ; lp[-1] = '/'; if (lp - line >= sizeof(line)) { printf("\tspool directory name too long\n"); return; } PRIV_START; nitems = scandir(SD, &queue, doselect, sortq); PRIV_END; 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) { if (strlcpy(lp, cp, sizeof(line) - (lp - line)) >= sizeof(line) - (lp - line)) printf("\tpath too long, %s/%s", SD, cp); else 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). */ if (strlcpy(lp, cp, sizeof(line) - (lp - line)) >= sizeof(line) - (lp - line)) printf("\tpath too long, %s/%s", SD, cp); else unlinkf(line); } } while (++i < nitems); } static void unlinkf(char *name) { PRIV_START; if (unlink(name) < 0) printf("\tcannot remove %s\n", name); else printf("\tremoved %s\n", name); PRIV_END; } /* * Enable queuing to the printer (allow lpr's). */ void enable(int argc, char **argv) { int c, status; char *cp1, *cp2; char prbuf[100]; if (argc == 1) { printf("Usage: enable {all | printer ...}\n"); return; } if (argc == 2 && strcmp(argv[1], "all") == 0) { printer = prbuf; while (cgetnext(&bp, printcapdb) > 0) { cp1 = prbuf; cp2 = bp; while ((c = *cp2++) && c != '|' && c != ':' && (cp1 - prbuf) < sizeof(prbuf) - 1) *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(void) { struct stat stbuf; if (cgetstr(bp, "sd", &SD) == -1) SD = _PATH_DEFSPOOL; if (cgetstr(bp, "lo", &LO) == -1) LO = DEFLOCK; (void)snprintf(line, sizeof(line), "%s/%s", SD, LO); printf("%s:\n", printer); /* * Turn off the group execute bit of the lock file to enable queuing. */ PRIV_START; if (stat(line, &stbuf) >= 0) { stbuf.st_mode &= ~S_IXGRP; if (chmod(line, stbuf.st_mode & 0777) < 0) printf("\tcannot enable queuing\n"); else printf("\tqueuing enabled\n"); } PRIV_END; } /* * Disable queuing. */ void disable(int argc, char **argv) { int c, status; char *cp1, *cp2; char prbuf[100]; if (argc == 1) { printf("Usage: disable {all | printer ...}\n"); return; } if (argc == 2 && strcmp(argv[1], "all") == 0) { printer = prbuf; while (cgetnext(&bp, printcapdb) > 0) { cp1 = prbuf; cp2 = bp; while ((c = *cp2++) && c != '|' && c != ':' && (cp1 - prbuf) < sizeof(prbuf) - 1) *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(void) { int fd; struct stat stbuf; if (cgetstr(bp, "sd", &SD) == -1) SD = _PATH_DEFSPOOL; if (cgetstr(bp, "lo", &LO) == -1) LO = DEFLOCK; (void)snprintf(line, sizeof(line), "%s/%s", SD, LO); printf("%s:\n", printer); /* * Turn on the group execute bit of the lock file to disable queuing. */ PRIV_START; if (stat(line, &stbuf) >= 0) { stbuf.st_mode |= S_IXGRP; if (chmod(line, stbuf.st_mode & 0777) < 0) printf("\tcannot disable queuing\n"); else printf("\tqueuing disabled\n"); } else if (errno == ENOENT) { if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0670)) < 0) printf("\tcannot create lock file\n"); else { (void)fchown(fd, DEFNUID, -1); (void)close(fd); printf("\tqueuing disabled\n"); } } else printf("\tcannot stat lock file\n"); PRIV_END; } /* * Disable queuing and printing and put a message into the status file * (reason for being down). */ void down(int argc, char **argv) { int c, status; char *cp1, *cp2; char prbuf[100]; if (argc == 1) { printf("Usage: down {all | printer} [message ...]\n"); return; } if (strcmp(argv[1], "all") == 0) { printer = prbuf; while (cgetnext(&bp, printcapdb) > 0) { cp1 = prbuf; cp2 = bp; while ((c = *cp2++) && c != '|' && c != ':' && (cp1 - prbuf) < sizeof(prbuf) - 1) *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(int argc, char **argv) { int fd; 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)snprintf(line, sizeof(line), "%s/%s", SD, LO); PRIV_START; if (stat(line, &stbuf) >= 0) { stbuf.st_mode |= (S_IXGRP|S_IXUSR); if (chmod(line, stbuf.st_mode & 0777) < 0) printf("\tcannot disable queuing\n"); else printf("\tprinter and queuing disabled\n"); } else if (errno == ENOENT) { if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0770)) < 0) printf("\tcannot create lock file\n"); else { (void)fchown(fd, DEFNUID, -1); (void)close(fd); printf("\tprinter and queuing disabled\n"); } PRIV_END; return; } else printf("\tcannot stat lock file\n"); /* * Write the message into the status file. */ (void)snprintf(line, sizeof(line), "%s/%s", SD, ST); fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0660); if (fd < 0 || flock(fd, LOCK_EX) < 0) { printf("\tcannot create status file\n"); PRIV_END; return; } PRIV_END; (void)fchown(fd, DEFNUID, -1); (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 - buf) < sizeof(buf) - 1 && (*cp1++ = *cp2++)) ; cp1[-1] = ' '; } cp1[-1] = '\n'; *cp1 = '\0'; (void)write(fd, buf, strlen(buf)); (void)close(fd); } /* * Exit lpc */ void quit(int argc, char **argv) { exit(0); } /* * Kill and restart the daemon. */ void restart(int argc, char **argv) { int c, status; char *cp1, *cp2; char prbuf[100]; if (argc == 1) { printf("Usage: restart {all | printer ...}\n"); return; } if (argc == 2 && strcmp(argv[1], "all") == 0) { printer = prbuf; while (cgetnext(&bp, printcapdb) > 0) { cp1 = prbuf; cp2 = bp; while ((c = *cp2++) && c != '|' && c != ':' && (cp1 - prbuf) < sizeof(prbuf) - 1) *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(int argc, char **argv) { int c, status; char *cp1, *cp2; char prbuf[100]; if (argc == 1) { printf("Usage: start {all | printer ...}\n"); return; } if (argc == 2 && strcmp(argv[1], "all") == 0) { printer = prbuf; while (cgetnext(&bp, printcapdb) > 0) { cp1 = prbuf; cp2 = bp; while ((c = *cp2++) && c != '|' && c != ':' && (cp1 - prbuf) < sizeof(prbuf) - 1) *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(int enable) { struct stat stbuf; if (cgetstr(bp, "sd", &SD) == -1) SD = _PATH_DEFSPOOL; if (cgetstr(bp, "lo", &LO) == -1) LO = DEFLOCK; (void)snprintf(line, sizeof(line), "%s/%s", SD, LO); printf("%s:\n", printer); /* * Turn off the owner execute bit of the lock file to enable printing. * If we are marking the printer "up" also turn off group execute bit. */ PRIV_START; if (enable && stat(line, &stbuf) >= 0) { if (enable == 2) stbuf.st_mode &= ~(S_IXUSR|S_IXGRP); else stbuf.st_mode &= ~S_IXUSR; if (chmod(line, stbuf.st_mode & 0777) < 0) printf("\tcannot enable printing\n"); else printf("\tprinting enabled\n"); } PRIV_END; 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(int argc, char **argv) { int c, status; char *cp1, *cp2; char prbuf[100]; if (argc == 1 || (argc == 2 && strcmp(argv[1], "all") == 0)) { printer = prbuf; while (cgetnext(&bp, printcapdb) > 0) { cp1 = prbuf; cp2 = bp; while ((c = *cp2++) && c != '|' && c != ':' && (cp1 - prbuf) < sizeof(prbuf) - 1) *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(void) { struct stat stbuf; int fd, i; 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)snprintf(line, sizeof(line), "%s/%s", SD, LO); PRIV_START; i = stat(line, &stbuf); PRIV_END; if (i >= 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"); } PRIV_START; dirp = opendir(SD); PRIV_END; if (dirp == 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); PRIV_START; fd = safe_open(line, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd < 0 || flock(fd, LOCK_SH|LOCK_NB) == 0) { (void)close(fd); /* unlocks as well */ printf("\tprinter idle\n"); return; } (void)close(fd); (void)snprintf(line, sizeof(line), "%s/%s", SD, ST); PRIV_START; fd = safe_open(line, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd >= 0) { (void)flock(fd, LOCK_SH); if (fstat(fd, &stbuf) == 0 && stbuf.st_size > 0) { putchar('\t'); 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(int argc, char **argv) { int c, status; char *cp1, *cp2; char prbuf[100]; if (argc == 1) { printf("Usage: stop {all | printer ...}\n"); return; } if (argc == 2 && strcmp(argv[1], "all") == 0) { printer = prbuf; while (cgetnext(&bp, printcapdb) > 0) { cp1 = prbuf; cp2 = bp; while ((c = *cp2++) && c != '|' && c != ':' && (cp1 - prbuf) < sizeof(prbuf) - 1) *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(void) { int fd; struct stat stbuf; if (cgetstr(bp, "sd", &SD) == -1) SD = _PATH_DEFSPOOL; if (cgetstr(bp, "lo", &LO) == -1) LO = DEFLOCK; (void)snprintf(line, sizeof(line), "%s/%s", SD, LO); printf("%s:\n", printer); /* * Turn on the owner execute bit of the lock file to disable printing. */ PRIV_START; if (stat(line, &stbuf) >= 0) { stbuf.st_mode |= S_IXUSR; if (chmod(line, stbuf.st_mode & 0777) < 0) printf("\tcannot disable printing\n"); else { upstat("printing disabled\n"); printf("\tprinting disabled\n"); } } else if (errno == ENOENT) { if ((fd = safe_open(line, O_WRONLY|O_CREAT|O_NOFOLLOW, 0760)) < 0) printf("\tcannot create lock file\n"); else { (void)fchown(fd, DEFNUID, -1); (void)close(fd); upstat("printing disabled\n"); printf("\tprinting disabled\n"); } } else printf("\tcannot stat lock file\n"); PRIV_END; } struct queue **queue; int nitems; time_t mtime; /* * Put the specified jobs at the top of printer queue. */ void topq(int argc, char **argv) { 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); PRIV_START; if (chdir(SD) < 0) { printf("\tcannot chdir to %s\n", SD); goto out; } PRIV_END; 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. */ PRIV_START; if (changed && stat(LO, &stbuf) >= 0) { stbuf.st_mode |= S_IXOTH; (void)chmod(LO, stbuf.st_mode & 0777); } out: PRIV_END; } /* * Reposition the job by changing the modification time of * the control file. */ static int touch(struct queue *q) { struct timeval tvp[2]; int ret; tvp[0].tv_sec = tvp[1].tv_sec = --mtime; tvp[0].tv_usec = tvp[1].tv_usec = 0; PRIV_START; ret = utimes(q->q_name, tvp); PRIV_END; return (ret); } /* * Checks if specified job name is in the printer's queue. * Returns: negative (-1) if argument name is not in the queue. */ int doarg(char *job) { struct queue **qq; int jobnum, fd, n; char *cp, *machine; int cnt = 0; FILE *fp; /* * Look for a job item consisting of system name, colon, number * (example: ucbarpa:114) */ if ((cp = strchr(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; ) { PRIV_START; fd = safe_open((*qq)->q_name, O_RDONLY|O_NOFOLLOW, 0); PRIV_END; if (fd < 0 || (fp = fdopen(fd, "r")) == NULL) { if (fd >= 0) close(fd); continue; } while (getcfline(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(int argc, char **argv) { int c, status; char *cp1, *cp2; char prbuf[100]; if (argc == 1) { printf("Usage: up {all | printer ...}\n"); return; } if (argc == 2 && strcmp(argv[1], "all") == 0) { printer = prbuf; while (cgetnext(&bp, printcapdb) > 0) { cp1 = prbuf; cp2 = bp; while ((c = *cp2++) && c != '|' && c != ':' && (cp1 - prbuf) < sizeof(prbuf) - 1) *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); } } lpr-2008.05.17.3+nmu1/lpc/cmdtab.c0000644000000000000000000000655507666757625013037 0ustar /* $OpenBSD: cmdtab.c,v 1.5 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: cmdtab.c,v 1.4 1995/11/15 22:27:34 pk Exp $ */ /* * 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. 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 #if 0 static const char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93"; #else static const char rcsid[] = "$OpenBSD: cmdtab.c,v 1.5 2003/06/02 23:36:53 millert Exp $"; #endif #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]); lpr-2008.05.17.3+nmu1/lpc/extern.h0000644000000000000000000000424107666757625013105 0ustar /* $OpenBSD: extern.h,v 1.5 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: extern.h,v 1.2 1995/11/15 22:27:36 pk Exp $ */ /* * 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. 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(int, char **); void disable(int, char **); void doabort(int, char **); void down(int, char **); void enable(int, char **); void help(int, char **); void quit(int, char **); void restart(int, char **); void startcmd(int, char **); void status(int, char **); void stop(int, char **); void topq(int, char **); void up(int, char **); __END_DECLS extern int NCMDS; extern struct cmd cmdtab[]; lpr-2008.05.17.3+nmu1/lpc/lpc.80000644000000000000000000001331411013656726012254 0ustar .\" $OpenBSD: lpc.8,v 1.13 2007/05/31 19:20:25 jmc Exp $ .\" $NetBSD: lpc.8,v 1.14 2002/01/19 03:22:19 wiz Exp $ .\" .\" 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. 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.5 (Berkeley) 4/28/95 .\" .Dd $Mdocdate: May 31 2007 $ .Dt LPC 8 .Os .Sh NAME .Nm lpc .Nd line printer control program .Sh SYNOPSIS .Nm lpc .Bk -words .Oo .Ar command .Op Ar argument ... .Oc .Ek .Sh DESCRIPTION .Nm 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 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 will prompt for commands from the standard input. If arguments are supplied, .Nm interprets the first argument as a command and the remaining arguments as parameters to the command. The standard input may be redirected causing .Nm 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 [ Ar command Ar ... ] .It Ic help No [ Ar command Ar ... ] 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 1 ) 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 1 . .Pp .It Xo Ic down No {\ all\ |\ printer\ } Ar message .Op Ar ... .Xc 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 users 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 .Nm 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 1 will report that there is no daemon present when this condition occurs. If the user is the superuser, 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 . .El .Sh FILES .Bl -tag -width /var/spool/output/*/lock -compact .It Pa /etc/printcap printer description file .It Pa /var/spool/output/* spool directories .It Pa /var/spool/output/*/lock lock file for queue control .El .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" You must be a member of group .Dq operator or user .Dq root to execute this command. .El .Sh SEE ALSO .Xr lpq 1 , .Xr lpr 1 , .Xr lprm 1 , .Xr printcap 5 , .Xr lpd 8 .Sh HISTORY The .Nm command appeared in .Bx 4.2 . lpr-2008.05.17.3+nmu1/lpc/lpc.c0000644000000000000000000001524310176607056012333 0ustar /* $OpenBSD: lpc.c,v 1.17 2004/09/30 18:20:06 millert Exp $ */ /* $NetBSD: lpc.c,v 1.11 2001/11/14 03:01:15 enami Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static const char sccsid[] = "@(#)lpc.c 8.3 (Berkeley) 4/28/95"; #else static const char rcsid[] = "$OpenBSD: lpc.c,v 1.17 2004/09/30 18:20:06 millert Exp $"; #endif #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include "lp.h" #include "lpc.h" #include "extern.h" #ifndef LPR_OPER #define LPR_OPER "operator" /* group name of lpr operators */ #endif /* * lpc -- line printer control program */ #define MAX_CMDLINE 200 #define MAX_MARGV 20 int fromatty; char cmdline[MAX_CMDLINE]; int margc; char *margv[MAX_MARGV]; static void cmdscanner(void); static struct cmd *getcmd(char *); static void intr(int); static void makeargv(void); static int ingroup(char *); int main(int argc, char **argv) { struct cmd *c; effective_uid = geteuid(); real_uid = getuid(); effective_gid = getegid(); real_gid = getgid(); PRIV_END; /* be safe */ openlog("lpc", 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 && real_uid && ingroup(LPR_OPER) == 0) { printf("?Privileged command\n"); exit(1); } (*c->c_handler)(argc, argv); exit(0); } fromatty = isatty(fileno(stdin)); signal(SIGINT, intr); for (;;) cmdscanner(); } volatile sig_atomic_t gotintr; static void intr(int signo) { if (!fromatty) _exit(0); gotintr = 1; } /* * Command parser. */ static void cmdscanner(void) { struct cmd *c; for (;;) { if (gotintr) { putchar('\n'); gotintr = 0; } if (fromatty) { printf("lpc> "); fflush(stdout); } siginterrupt(SIGINT, 1); if (fgets(cmdline, MAX_CMDLINE, stdin) == NULL) { if (errno == EINTR && gotintr) { siginterrupt(SIGINT, 0); return; } siginterrupt(SIGINT, 0); quit(0, NULL); } siginterrupt(SIGINT, 0); makeargv(); if (margc == 0) break; 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() && ingroup(LPR_OPER) == 0) { printf("?Privileged command\n"); continue; } (*c->c_handler)(margc, margv); } } static struct cmd * getcmd(char *name) { char *p, *q; struct cmd *c, *found; int nmatches, longest; longest = 0; nmatches = 0; found = 0; for (c = cmdtab; (p = c->c_name) != NULL; 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(void) { char *cp = cmdline; char **ap = margv; margc = 0; while (margc < MAX_MARGV - 1 && (*ap = strsep(&cp, " \t\n")) != NULL) { if (**ap != '\0') { ap++; margc++; } } *ap = NULL; } #define HELPINDENT ((int)sizeof("directory")) /* * Help command. */ void help(int argc, char **argv) { struct cmd *c; if (argc == 1) { int i, j, w; int columns, width = 0, lines; 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) { 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); } } /* * return non-zero if the user is a member of the given group */ static int ingroup(char *grname) { static struct group *gptr = NULL; static gid_t groups[NGROUPS]; static int ngroups; gid_t gid; int i; if (gptr == NULL) { if ((gptr = getgrnam(grname)) == NULL) { warnx("Warning: unknown group `%s'", grname); return(0); } if ((ngroups = getgroups(NGROUPS, groups)) < 0) err(1, "getgroups"); } gid = gptr->gr_gid; for (i = 0; i < ngroups; i++) if (gid == groups[i]) return(1); return(0); } lpr-2008.05.17.3+nmu1/lpc/lpc.h0000644000000000000000000000370307666757625012360 0ustar /* $OpenBSD: lpc.h,v 1.5 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: lpc.h,v 1.2 1995/11/15 22:27:44 pk Exp $ */ /* * 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. 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)(int, char *[]); int c_priv; /* privileged command */ }; lpr-2008.05.17.3+nmu1/lpd/0000755000000000000000000000000013416173536011406 5ustar lpr-2008.05.17.3+nmu1/lpd/Makefile0000644000000000000000000000073110176611664013046 0ustar # from: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $OpenBSD: Makefile,v 1.4 2002/06/08 01:53:43 millert Exp $ PROG= lpd CFLAGS+=-I${.CURDIR}/../common_source MAN= lpd.8 SRCS= rcmd.c lpd.c printjob.c recvjob.c ../common_source/displayq.c ../common_source/rmjob.c ../common_source/startdaemon.c \ lpdchar.c ../common_source/common.c key.c modes.c ../common_source/common_vars.c ../common_source/getcap.c ../common_source/vis.c BINGRP= daemon BINMODE=2550 include ../Makefile.in lpr-2008.05.17.3+nmu1/lpd/extern.h0000644000000000000000000000514607666757625013113 0ustar /* $OpenBSD: extern.h,v 1.6 2003/06/02 23:36:53 millert Exp $ */ /* * 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. 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 #include #include /* * from stty.h */ struct info { int fd; /* file descriptor */ int ldisc; /* line discipline */ int off; /* turn off */ int set; /* need set */ int wset; /* need window set */ char *arg; /* argument */ struct termios t; /* terminal info */ struct winsize win; /* window info */ }; int ksearch(char ***, struct info *); int msearch(char ***, struct info *); void printjob(void); void recvjob(void); void sttyclearflags(struct termios *tp, int flags); void sttysetflags(struct termios *tp, int flags); void sttyclearlflags(struct termios *tp, int flags); void sttysetlflags(struct termios *tp, int flags); lpr-2008.05.17.3+nmu1/lpd/key.c0000644000000000000000000001325110176611664012343 0ustar /* $OpenBSD: key.c,v 1.6 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: key.c,v 1.3 1997/10/20 08:08:28 scottr Exp $ */ /*- * Copyright (c) 1991, 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. 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 #if 0 static const char sccsid[] = "@(#)key.c 8.3 (Berkeley) 4/2/94"; #else static const char rcsid[] = "$OpenBSD: key.c,v 1.6 2003/06/02 23:36:53 millert Exp $"; #endif #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include "lp.h" #include "extern.h" __BEGIN_DECLS static int c_key(const void *, const void *); void f_cbreak(struct info *); void f_columns(struct info *); void f_dec(struct info *); /* void f_extproc(struct info *); */ void f_ispeed(struct info *); void f_nl(struct info *); void f_ospeed(struct info *); void f_raw(struct info *); void f_rows(struct info *); void f_sane(struct info *); void f_tty(struct info *); __END_DECLS static struct key { char *name; /* name */ void (*f)(struct info *); /* function */ #define F_NEEDARG 0x01 /* needs an argument */ #define F_OFFOK 0x02 /* can turn off */ int flags; } const keys[] = { { "cbreak", f_cbreak, F_OFFOK }, { "cols", f_columns, F_NEEDARG }, { "columns", f_columns, F_NEEDARG }, { "cooked", f_sane, 0 }, { "dec", f_dec, 0 }, { "ispeed", f_ispeed, F_NEEDARG }, { "new", f_tty, 0 }, { "nl", f_nl, F_OFFOK }, { "old", f_tty, 0 }, { "ospeed", f_ospeed, F_NEEDARG }, { "raw", f_raw, F_OFFOK }, { "rows", f_rows, F_NEEDARG }, { "sane", f_sane, 0 }, { "tty", f_tty, 0 }, }; static int c_key(const void *a, const void *b) { return (strcmp(((struct key *)a)->name, ((struct key *)b)->name)); } int ksearch(char ***argvp, struct info *ip) { char *name; struct key *kp, tmp; name = **argvp; if (*name == '-') { ip->off = 1; ++name; } else ip->off = 0; tmp.name = name; if (!(kp = (struct key *)bsearch(&tmp, keys, sizeof(keys)/sizeof(struct key), sizeof(struct key), c_key))) return (0); if (!(kp->flags & F_OFFOK) && ip->off) { syslog(LOG_INFO, "%s: illegal option: %s", printer, name); return (1); } if (kp->flags & F_NEEDARG && !(ip->arg = *++*argvp)) { syslog(LOG_INFO, "%s: option requires an argument: %s", printer, name); return (1); } kp->f(ip); return (1); } void f_cbreak(struct info *ip) { if (ip->off) f_sane(ip); else { ip->t.c_iflag |= BRKINT|IXON|IMAXBEL; ip->t.c_oflag |= OPOST; ip->t.c_lflag |= ISIG|IEXTEN; ip->t.c_lflag &= ~ICANON; ip->set = 1; } } void f_columns(struct info *ip) { ip->win.ws_col = atoi(ip->arg); ip->wset = 1; } void f_dec(struct info *ip) { ip->t.c_cc[VERASE] = (u_char)0177; ip->t.c_cc[VKILL] = CTRL('u'); ip->t.c_cc[VINTR] = CTRL('c'); ip->t.c_lflag &= ~ECHOPRT; ip->t.c_lflag |= ECHOE|ECHOKE|ECHOCTL; ip->t.c_iflag &= ~IXANY; ip->set = 1; } /* void f_extproc(struct info *ip) { if (ip->set) { int tmp = 1; (void)ioctl(ip->fd, TIOCEXT, &tmp); } else { int tmp = 0; (void)ioctl(ip->fd, TIOCEXT, &tmp); } } */ void f_ispeed(struct info *ip) { cfsetispeed(&ip->t, atoi(ip->arg)); ip->set = 1; } void f_nl(struct info *ip) { if (ip->off) { ip->t.c_iflag |= ICRNL; ip->t.c_oflag |= ONLCR; } else { ip->t.c_iflag &= ~ICRNL; ip->t.c_oflag &= ~ONLCR; } ip->set = 1; } void f_ospeed(struct info *ip) { cfsetospeed(&ip->t, atoi(ip->arg)); ip->set = 1; } void f_raw(struct info *ip) { if (ip->off) f_sane(ip); else { cfmakeraw(&ip->t); ip->t.c_cflag &= ~(CSIZE|PARENB); ip->t.c_cflag |= CS8; ip->set = 1; } } void f_rows(struct info *ip) { ip->win.ws_row = atoi(ip->arg); ip->wset = 1; } void f_sane(struct info *ip) { ip->t.c_cflag = TTYDEF_CFLAG | (ip->t.c_cflag & (CLOCAL|CRTSCTS)); ip->t.c_iflag = TTYDEF_IFLAG; ip->t.c_iflag |= ICRNL; /* preserve user-preference flags in lflag */ #define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|TOSTOP|NOFLSH) ip->t.c_lflag = TTYDEF_LFLAG | (ip->t.c_lflag & LKEEP); ip->t.c_oflag = TTYDEF_OFLAG; ip->set = 1; } void f_tty(struct info *ip) { int tmp; tmp = N_TTY; if (ioctl(0, TIOCSETD, &tmp) < 0) syslog(LOG_ERR, "%s: ioctl(TIOCSETD): %m", printer); } lpr-2008.05.17.3+nmu1/lpd/lpd.80000644000000000000000000002245111013657060012250 0ustar .\" $OpenBSD: lpd.8,v 1.21 2008/04/15 07:54:48 ajacoutot Exp $ .\" $NetBSD: lpd.8,v 1.23 2002/02/08 01:38:50 ross Exp $ .\" .\" 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. 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 $Mdocdate: April 15 2008 $ .Dt LPD 8 .Os .Sh NAME .Nm lpd .Nd line printer spooler daemon .Sh SYNOPSIS .Nm lpd .Op Fl dlrs .Op Fl b Ar bind-address .Op Fl n Ar maxchild .Op Fl w Ar maxwait .Op port .Sh DESCRIPTION .Nm 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 The options are as follows: .Bl -tag -width Ds .It Fl b Ar bind-address Normally, if the .Fl s option is not specified, .Nm will listen on all network interfaces for incoming TCP connections. The .Fl b option, followed by a .Ar bind-address specifies that .Nm should listen on that address instead of INADDR_ANY. Multiple .Fl b options are permitted, allowing a list of addresses to be specified. Use of this option silently overrides the .Fl s option if it is also present on the command line. .Ar bind-address can be a numeric host name in IPV4 or IPV6 notation, or a symbolic host name which will be looked up in the normal way. .It Fl d The .Fl d option turns on the .Dv SO_DEBUG .Xr socket 2 option. See .Xr setsockopt 2 for more details. .It Fl l The .Fl l flag causes .Nm to log valid requests received from the network. This can be useful for debugging purposes. .It Fl n Ar maxchild The .Fl n flag sets .Ar maxchild as the maximum number of child processes that .Nm will spawn. The default is 32. .It Fl r The .Fl r flag allows the .Dq of filter to be used if specified for a remote printer. Traditionally, .Nm would not use the output filter for remote printers. .It Fl s The .Fl s flag selects .Dq secure mode, in which .Nm does not listen on a TCP socket but only takes commands from a .Ux domain socket. This is valuable when the machine on which .Nm runs is subject to attack over the network and it is desired that the machine be protected from attempts to remotely fill spools and similar attacks. .It Fl w Ar maxwait The .Fl w flag sets .Ar maxwait as the wait time (in seconds) for dead remote server detection. If no response is returned from a connected server within this period, the connection is closed and a message logged. The default is 300 seconds. .El .Pp If the .Op port parameter is passed, .Nm listens on this port instead of the usual .Dq printer/tcp port from .Pa /etc/services . .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 (which follows the same syntax as .Xr hosts.equiv 5 ) . Second, if the .Dq rs capability is specified in the .Xr printcap 5 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 .Nm performs reverse DNS lookups on network clients. If a client hostname cannot be determined from its IP address, the print request will be silently dropped. This is important to note when debugging print problems in dynamic address environments. .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 1 was invoked. .It P Person. Login name of the person who invoked .Xr lpr 1 . This is used to verify ownership by .Xr lprm 1 . .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 .Dq 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 Stanford. .It g Graph File. The file contains data produced by .Ic plot . .It c Cifplot File. The file contains data produced by .Ic 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 1 is invoked in a pipeline). .El .Pp If a file cannot be opened, a message will be logged via .Xr syslog 3 using the .Dv LOG_LPR facility. .Nm 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 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 for the programs .Xr lpq 1 and .Xr lprm 1 . .Sh FILES .Bl -tag -width "/var/spool/output/*/minfree" -compact .It Pa /etc/printcap printer description file .It Pa /var/run/lpd.pid lock file for .Nm .It Pa /var/spool/output/* spool directories .It Pa /var/spool/output/*/minfree minimum free space to leave .It Pa /dev/lp* line printer devices .It Pa /var/run/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 lpq 1 , .Xr lpr 1 , .Xr lprm 1 , .Xr syslog 3 , .Xr hosts 5 , .Xr hosts.equiv 5 , .Xr printcap 5 , .Xr resolv.conf 5 , .Xr lpc 8 , .Xr pac 8 .Rs .%T "4.3BSD Line Printer Spooler Manual" .Re .Sh HISTORY An .Nm daemon appeared in .At v6 . .Pp .Nm previously required that clients connected using a privileged port (below 1024). This restriction was removed because it does not provide additional security and also because many modern clients connect using an unprivileged port. lpr-2008.05.17.3+nmu1/lpd/lpd.c0000644000000000000000000005227611013670124012327 0ustar /* $OpenBSD: lpd.c,v 1.47 2007/09/02 15:19:38 deraadt Exp $ */ /* $NetBSD: lpd.c,v 1.33 2002/01/21 14:42:29 wiz Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static const char sccsid[] = "@(#)lpd.c 8.7 (Berkeley) 5/10/95"; #else static const char rcsid[] = "$OpenBSD: lpd.c,v 1.47 2007/09/02 15:19:38 deraadt Exp $"; #endif #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 root and the group daemon. * 2. Files in spooling area are owned by user daemon, group daemon, * and are mode 660. * 3. lpd runs as root but spends most of its time with its effective * uid and gid set to the uid/gid specified in the passwd entry for * DEFUID ("lp"). * 4. lpr and lprm run setuid daemon and setgrp daemon. lpr opens * files to be printed with its real uid/gid and writes to * the spool dir with its effective uid/gid (i.e. daemon). * lprm need to run as user daemon so it can kill lpd. * 5. lpc and lpq run setgrp daemon. * * Users can't touch the spool w/o the help of one of the lp* programs. */ #include #include #include #include #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" #define _PATH_FHSLOCK "/var/spool/lpd/lpd.lock" /* symlink to _PATH_MASTERLOCK to satisfy FHS */ int lflag; /* log requests flag */ int rflag; /* allow 'of' for remote printers */ int sflag; /* secure (no inet) flag */ int from_remote; /* from remote socket */ char **blist; /* list of addresses to bind(2) to */ int blist_size; int blist_addrs; volatile sig_atomic_t child_count; /* number of kids forked */ static void reapchild(int); static void mcleanup(int); static void doit(void); static void startup(void); static void chkhost(struct sockaddr *); static int ckqueue(char *); static void usage(void); static int *socksetup(int, int, const char *); extern int __ivaliduser_sa(FILE *, struct sockaddr *, socklen_t, const char *, const char *); /* unused, needed for lpc */ volatile sig_atomic_t gotintr; int main(int argc, char **argv) { fd_set defreadfds; struct passwd *pw; struct sockaddr_un un, fromunix; struct sockaddr_storage frominet; sigset_t mask, omask; int lfd, i, f, funix, *finet; int options, maxfd; long l; long child_max = 32; /* more than enough to hose the system */ struct servent *sp; const char *port = "printer"; char *cp; if (geteuid() != 0) errx(1, "must run as root"); /* * We want to run with euid of daemon most of the time. */ if ((pw = getpwnam(DEFUID)) == NULL) errx(1, "'lp' uid not in password file"); real_uid = pw->pw_uid; real_gid = pw->pw_gid; effective_uid = 0; effective_gid = getegid(); setresgid(real_gid, real_gid, effective_gid); setresuid(real_uid, real_uid, effective_uid); PRIV_END; /* run as daemon for most things */ options = 0; gethostname(host, sizeof(host)); while ((i = getopt(argc, argv, "b:dln:rsw:W")) != -1) { switch (i) { case 'b': if (blist_addrs >= blist_size) { if (blist == NULL) { blist_size += sizeof(char *) * 4; blist = malloc(blist_size); } else { char **newblist; int newblist_size = blist_size + sizeof(char *) * 4; newblist = realloc(blist, newblist_size); if (newblist == NULL) { free(blist); blist_size = 0; blist = NULL; } blist = newblist; blist_size = newblist_size; } if (blist == NULL) err(1, "cant allocate bind addr list"); } blist[blist_addrs] = strdup(optarg); if (blist[blist_addrs++] == NULL) err(1, NULL); break; case 'd': options |= SO_DEBUG; break; case 'l': lflag++; break; case 'n': child_max = strtol(optarg, &cp, 10); if (*cp != '\0' || child_max < 0 || child_max > 1024) errx(1, "invalid number of children: %s", optarg); break; case 'r': rflag++; break; case 's': sflag++; break; case 'w': l = strtol(optarg, &cp, 10); if (*cp != '\0' || l < 0 || l >= INT_MAX) errx(1, "wait time must be postive integer: %s", optarg); wait_time = (u_int)l; if (wait_time < 30) warnx("warning: wait time less than 30 seconds"); break; case 'W': /* XXX deprecate */ break; default: usage(); break; } } argc -= optind; argv += optind; switch (argc) { case 1: port = argv[0]; l = strtol(port, &cp, 10); if (*cp != '\0' || l <= 0 || l > USHRT_MAX) errx(1, "port # %s is invalid", port); break; case 0: sp = getservbyname(port, "tcp"); if (sp == NULL) errx(1, "%s/tcp: unknown service", port); break; default: usage(); } #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); PRIV_START; lfd = open(_PATH_MASTERLOCK, O_WRONLY|O_CREAT/*|O_EXLOCK*/|O_NONBLOCK, 0644); symlink(_PATH_MASTERLOCK, _PATH_FHSLOCK); PRIV_END; if (lfd < 0 || flock(lfd, LOCK_EX|LOCK_NB) < 0) { if (errno == EWOULDBLOCK) /* active daemon present */ exit(0); syslog(LOG_ERR, "%s: %m", _PATH_MASTERLOCK); exit(1); } ftruncate(lfd, 0); /* * write process id for others to know */ (void)snprintf(line, sizeof(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(); PRIV_START; (void)unlink(_PATH_SOCKETNAME); PRIV_END; funix = socket(AF_LOCAL, SOCK_STREAM, 0); if (funix < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); } sigemptyset(&mask); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGQUIT); sigaddset(&mask, SIGTERM); sigprocmask(SIG_BLOCK, &mask, &omask); signal(SIGHUP, mcleanup); signal(SIGINT, mcleanup); signal(SIGQUIT, mcleanup); signal(SIGTERM, mcleanup); memset(&un, 0, sizeof(un)); un.sun_family = AF_LOCAL; strlcpy(un.sun_path, _PATH_SOCKETNAME, sizeof(un.sun_path)); PRIV_START; if (bind(funix, (struct sockaddr *)&un, SUN_LEN(&un)) < 0) { syslog(LOG_ERR, "ubind: %m"); exit(1); } chmod(_PATH_SOCKETNAME, 0660); chown(_PATH_SOCKETNAME, -1, real_gid); PRIV_END; (void)umask(0); /* XXX */ sigprocmask(SIG_SETMASK, &omask, NULL); FD_ZERO(&defreadfds); FD_SET(funix, &defreadfds); listen(funix, 5); if (!sflag || blist_addrs) finet = socksetup(PF_UNSPEC, options, port); else finet = NULL; /* pretend we couldn't open TCP socket. */ if (blist != NULL) { for (i = 0; i < blist_addrs; i++) free(blist[i]); free(blist); } maxfd = funix; if (finet) { for (i = 1; i <= *finet; i++) { FD_SET(finet[i], &defreadfds); listen(finet[i], 5); if (finet[i] > maxfd) maxfd = finet[i]; } } /* * Main loop: accept, do a request, continue. */ memset(&frominet, 0, sizeof(frominet)); memset(&fromunix, 0, sizeof(fromunix)); for (;;) { int domain, nfds, s; socklen_t fromlen = -1; fd_set readfds; short sleeptime = 10; /* overflows in about 2 hours */ while (child_max < child_count) { syslog(LOG_WARNING, "too many children, sleeping for %d seconds", sleeptime); sleep(sleeptime); sleeptime <<= 1; if (sleeptime < 0) { syslog(LOG_CRIT, "sleeptime overflowed! help!"); sleeptime = 10; } } /*FD_COPY(defreadfds, readfds);*/ memcpy( &readfds, &defreadfds, sizeof(readfds)); nfds = select(maxfd + 1, &readfds, NULL, NULL, NULL); if (nfds <= 0) { if (nfds < 0 && errno != EINTR) syslog(LOG_WARNING, "select: %m"); continue; } if (FD_ISSET(funix, &readfds)) { domain = AF_LOCAL; fromlen = sizeof(fromunix); s = accept(funix, (struct sockaddr *)&fromunix, &fromlen); } else { domain = AF_INET; s = -1; for (i = 1; i <= *finet; i++) if (FD_ISSET(finet[i], &readfds)) { in_port_t port; fromlen = sizeof(frominet); s = accept(finet[i], (struct sockaddr *)&frominet, &fromlen); switch (frominet.ss_family) { case AF_INET: port = ((struct sockaddr_in *) &frominet)->sin_port; break; case AF_INET6: port = ((struct sockaddr_in6 *) &frominet)->sin6_port; break; default: port = 0; } /* check for ftp bounce attack */ if (port == htons(20)) { close(s); continue; } } } if (s < 0) { if (errno != EINTR) syslog(LOG_WARNING, "accept: %m"); continue; } switch (fork()) { case 0: signal(SIGCHLD, SIG_DFL); signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGTERM, SIG_IGN); (void)close(funix); if (!sflag && finet) for (i = 1; i <= *finet; i++) (void)close(finet[i]); if (s != STDOUT_FILENO) { dup2(s, STDOUT_FILENO); (void)close(s); } if (domain == AF_INET) { /* for both AF_INET and AF_INET6 */ from_remote = 1; chkhost((struct sockaddr *)&frominet); } else from_remote = 0; doit(); exit(0); case -1: syslog(LOG_WARNING, "fork: %m, sleeping for 10 seconds..."); sleep(10); continue; default: child_count++; } (void)close(s); } } static void reapchild(int signo) { int save_errno = errno; int status; while (waitpid((pid_t)-1, &status, WNOHANG) > 0) child_count--; errno = save_errno; } static void mcleanup(int signo) { /* struct syslog_data sdata = SYSLOG_DATA_INIT; */ if (lflag) syslog(LOG_INFO, /*&sdata,*/ "exiting"); PRIV_START; unlink(_PATH_SOCKETNAME); unlink(_PATH_MASTERLOCK); unlink(_PATH_FHSLOCK); _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[NI_MAXHOST]; /* 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(void) { char *cp; int n; for (;;) { cp = cbuf; do { if (cp >= &cbuf[sizeof(cbuf) - 1]) fatal("Command line too long"); if ((n = read(STDOUT_FILENO, 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[(int)*cp], cp+1); /*setproctitle("serving %s: %s %s", from, cmdnames[(int)*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; if (*printer == '\0') printer = DEFLP; printjob(); break; case '\2': /* receive files to be queued */ if (!from_remote) { syslog(LOG_INFO, "illegal request (%d)", *cp); exit(1); } printer = cp; if (*printer == '\0') printer = DEFLP; recvjob(); break; case '\3': /* display the queue (short form) */ case '\4': /* display the queue (long form) */ printer = cp; if (*printer == '\0') printer = DEFLP; 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; if (*printer == '\0') printer = DEFLP; 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(void) { char *buf, *cp; /* * Restart the daemons. */ while (cgetnext(&buf, printcapdb) > 0) { if (ckqueue(buf) <= 0) { free(buf); continue; /* no work to do for this printer */ } for (cp = buf; *cp; cp++) if (*cp == '|' || *cp == ':') { *cp = '\0'; break; } if (lflag) syslog(LOG_INFO, "work for %s", buf); switch (fork()) { case -1: syslog(LOG_WARNING, "startup: cannot fork"); mcleanup(0); /* NOTREACHED */ case 0: printer = buf; /*setproctitle("working on printer %s", printer);*/ cgetclose(); printjob(); /* NOTREACHED */ default: child_count++; free(buf); } } } /* * Make sure there's some work to do before forking off a child * XXX - could be common w/ lpq */ static int ckqueue(char *cap) { struct dirent *d; DIR *dirp; char *spooldir; int free_spooldir = 1; if (cgetstr(cap, "sd", &spooldir) == -1){ spooldir = _PATH_DEFSPOOL; free_spooldir = 0; } dirp = opendir(spooldir); if (free_spooldir) free(spooldir); if (dirp == NULL) return (-1); while ((d = readdir(dirp)) != NULL) { if (d->d_name[0] == 'c' && d->d_name[1] == 'f') { closedir(dirp); return (1); /* found a cf file */ } } closedir(dirp); return (0); } #define DUMMY ":nobody::" /* * Check to see if the from host has access to the line printer. */ static void chkhost(struct sockaddr *f) { struct addrinfo hints, *res, *r; FILE *hostf; int first = 1; int good = 0; char host[NI_MAXHOST], ip[NI_MAXHOST]; char serv[NI_MAXSERV]; int error; int len = 0; if( f->sa_family == AF_INET6 ) len = sizeof( struct sockaddr_in6 ); else if( f->sa_family == AF_INET ) len = sizeof( struct sockaddr_in ); error = getnameinfo(f, /*f->sa_*/len, NULL, 0, serv, sizeof(serv), NI_NUMERICSERV); if (error || !len) fatal("Malformed from address"); /* Need real hostname for temporary filenames */ error = getnameinfo(f, /*f->sa_*/len, host, sizeof(host), NULL, 0, NI_NAMEREQD); if (error) { error = getnameinfo(f, /*f->sa_*/len, host, sizeof(host), NULL, 0, NI_NUMERICHOST); if (error) fatal("Host name for your address unknown"); else fatal("Host name for your address (%s) unknown", host); } (void)strlcpy(fromb, host, sizeof(fromb)); from = fromb; /* need address in stringform for comparison (no DNS lookup here) */ error = getnameinfo(f, /*f->sa_*/len, host, sizeof(host), NULL, 0, NI_NUMERICHOST); if (error) fatal("Cannot print address"); /* Check for spoof, ala rlogind */ memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ error = getaddrinfo(fromb, NULL, &hints, &res); if (error) { fatal("hostname for your address (%s) unknown: %s", host, gai_strerror(error)); } for (good = 0, r = res; good == 0 && r; r = r->ai_next) { error = getnameinfo(r->ai_addr, r->ai_addrlen, ip, sizeof(ip), NULL, 0, NI_NUMERICHOST); if (!error && !strcmp(host, ip)) good = 1; } if (res) freeaddrinfo(res); if (good == 0) fatal("address for your hostname (%s) not matched", host); /* setproctitle("serving %s", from); */ PRIV_START; hostf = fopen(_PATH_HOSTSEQUIV, "r"); PRIV_END; again: if (hostf) { if (__ivaliduser_sa(hostf, f, len, DUMMY, DUMMY) == 0) { (void)fclose(hostf); return; } (void)fclose(hostf); } if (first == 1) { first = 0; PRIV_START; hostf = fopen(_PATH_HOSTSLPD, "r"); PRIV_END; goto again; } fatal("Your host does not have line printer access"); /*NOTREACHED*/ } static void usage(void) { extern char *__progname; fprintf(stderr, "usage: %s [-dlrs] [-b bind-address] [-n maxchild] " "[-w maxwait] [port]\n", __progname); exit(1); } /* * Setup server socket for specified address family. * If af is PF_UNSPEC more than one socket may be returned. * The returned list is dynamically allocated, so the caller needs to free it. */ int * socksetup(int af, int options, const char *port) { struct addrinfo hints, *res, *r; int error, maxs = 0, *s, *socks = NULL, *newsocks, blidx = 0; const int on = 1; do { memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = af; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo((blist_addrs == 0) ? NULL : blist[blidx], port ? port : "printer", &hints, &res); if (error) { if (blist_addrs) syslog(LOG_ERR, "%s: %s", blist[blidx], gai_strerror(error)); else syslog(LOG_ERR, "%s", gai_strerror(error)); mcleanup(0); } /* Count max number of sockets we may open */ for (r = res; r; r = r->ai_next, maxs++) ; if (socks == NULL) { socks = calloc(maxs + 1, sizeof(int)); if (socks) *socks = 0; /* num of sockets ctr at start */ } else { newsocks = realloc(socks, (maxs + 1) * sizeof(int)); if (newsocks) socks = newsocks; else { free(socks); socks = NULL; } } if (!socks) { syslog(LOG_ERR, "couldn't allocate memory for sockets"); mcleanup(0); } s = socks + *socks + 1; for (r = res; r; r = r->ai_next) { int bind_retry = 0; *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); if (*s < 0) { syslog(LOG_DEBUG, "socket(): %m"); continue; } if (options & SO_DEBUG) if (setsockopt(*s, SOL_SOCKET, SO_DEBUG, &on, sizeof(on)) < 0) { syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); close (*s); continue; } if( r->ai_family == AF_INET6 ){ struct protoent * pe = getprotobyname( "ipv6" ); if( pe && setsockopt( *s, IPPROTO_IPV6/*pe->p_proto*/, IPV6_V6ONLY, &on, sizeof(on)) == -1 ){ syslog( LOG_DEBUG, "setsockopt() failed: %m - IPV6 socked NOT opened"); continue; } } while( bind_retry++ < 5 ){ PRIV_START; error = bind(*s, r->ai_addr, r->ai_addrlen); PRIV_END; if (error < 0 && errno == EADDRINUSE ){ syslog(LOG_DEBUG, "bind(): %m -- Waiting 7 sec. and retrying"); sleep(7); continue; } break; } if( error < 0 ){ syslog(LOG_DEBUG, "bind(): %m"); close (*s); } *socks = *socks + 1; s++; } if (res) freeaddrinfo(res); } while (++blidx < blist_addrs); if (socks == NULL || *socks == 0) { syslog(LOG_ERR, "Couldn't bind to any socket"); if (socks != NULL) free(socks); mcleanup(0); } return(socks); } lpr-2008.05.17.3+nmu1/lpd/lpdchar.c0000644000000000000000000003711607666757625013220 0ustar /* $OpenBSD: lpdchar.c,v 1.5 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: lpdchar.c,v 1.5 1997/07/17 05:44:32 mikel Exp $ */ /* * 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. 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 #if 0 static const char sccsid[] = "@(#)lpdchar.c 8.1 (Berkeley) 6/6/93"; #else static const char rcsid[] = "$OpenBSD: lpdchar.c,v 1.5 2003/06/02 23:36:53 millert Exp $"; #endif #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 const 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 */ }; lpr-2008.05.17.3+nmu1/lpd/modes.c0000644000000000000000000001515511554307314012662 0ustar /* $OpenBSD: modes.c,v 1.6 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: modes.c,v 1.3 1997/10/20 08:08:31 scottr Exp $ */ /*- * Copyright (c) 1991, 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. 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 #if 0 static const char sccsid[] = "@(#)modes.c 8.3 (Berkeley) 4/2/94"; #else static const char rcsid[] = "$OpenBSD: modes.c,v 1.6 2003/06/02 23:36:53 millert Exp $"; #endif #endif /* not lint */ #include #include #include #include #include #include "extern.h" struct modes { char *name; long set; long unset; }; /* * The code in optlist() depends on minus options following regular * options, i.e. "foo" must immediately precede "-foo". */ const struct modes cmodes[] = { { "cs5", CS5, CSIZE }, { "cs6", CS6, CSIZE }, { "cs7", CS7, CSIZE }, { "cs8", CS8, CSIZE }, { "cstopb", CSTOPB, 0 }, { "-cstopb", 0, CSTOPB }, { "cread", CREAD, 0 }, { "-cread", 0, CREAD }, { "parenb", PARENB, 0 }, { "-parenb", 0, PARENB }, { "parodd", PARODD, 0 }, { "-parodd", 0, PARODD }, { "parity", PARENB | CS7, PARODD | CSIZE }, { "-parity", CS8, PARODD | PARENB | CSIZE }, { "evenp", PARENB | CS7, PARODD | CSIZE }, { "-evenp", CS8, PARODD | PARENB | CSIZE }, { "oddp", PARENB | CS7 | PARODD, CSIZE }, { "-oddp", CS8, PARODD | PARENB | CSIZE }, { "pass8", CS8, PARODD | PARENB | CSIZE }, { "-pass8", PARENB | CS7, PARODD | CSIZE }, { "hupcl", HUPCL, 0 }, { "-hupcl", 0, HUPCL }, { "hup", HUPCL, 0 }, { "-hup", 0, HUPCL }, { "clocal", CLOCAL, 0 }, { "-clocal", 0, CLOCAL }, { "crtscts", CRTSCTS, 0 }, { "-crtscts", 0, CRTSCTS }, { NULL }, }; const struct modes imodes[] = { { "ignbrk", IGNBRK, 0 }, { "-ignbrk", 0, IGNBRK }, { "brkint", BRKINT, 0 }, { "-brkint", 0, BRKINT }, { "ignpar", IGNPAR, 0 }, { "-ignpar", 0, IGNPAR }, { "parmrk", PARMRK, 0 }, { "-parmrk", 0, PARMRK }, { "inpck", INPCK, 0 }, { "-inpck", 0, INPCK }, { "istrip", ISTRIP, 0 }, { "-istrip", 0, ISTRIP }, { "inlcr", INLCR, 0 }, { "-inlcr", 0, INLCR }, { "igncr", IGNCR, 0 }, { "-igncr", 0, IGNCR }, { "icrnl", ICRNL, 0 }, { "-icrnl", 0, ICRNL }, #ifdef IUCLC { "iuclc", IUCLC, 0 }, { "-iuclc", 0, IUCLC }, #endif { "ixon", IXON, 0 }, { "-ixon", 0, IXON }, { "flow", IXON, 0 }, { "-flow", 0, IXON }, { "ixoff", IXOFF, 0 }, { "-ixoff", 0, IXOFF }, { "tandem", IXOFF, 0 }, { "-tandem", 0, IXOFF }, { "ixany", IXANY, 0 }, { "-ixany", 0, IXANY }, { "decctlq", 0, IXANY }, { "-decctlq", IXANY, 0 }, { "imaxbel", IMAXBEL, 0 }, { "-imaxbel", 0, IMAXBEL }, { NULL }, }; const struct modes lmodes[] = { { "echo", ECHO, 0 }, { "-echo", 0, ECHO }, { "echoe", ECHOE, 0 }, { "-echoe", 0, ECHOE }, { "crterase", ECHOE, 0 }, { "-crterase", 0, ECHOE }, { "crtbs", ECHOE, 0 }, /* crtbs not supported, close enough */ { "-crtbs", 0, ECHOE }, { "echok", ECHOK, 0 }, { "-echok", 0, ECHOK }, { "echoke", ECHOKE, 0 }, { "-echoke", 0, ECHOKE }, { "crtkill", ECHOKE, 0 }, { "-crtkill", 0, ECHOKE }, { "iexten", IEXTEN, 0 }, { "-iexten", 0, IEXTEN }, { "echonl", ECHONL, 0 }, { "-echonl", 0, ECHONL }, { "echoctl", ECHOCTL, 0 }, { "-echoctl", 0, ECHOCTL }, { "ctlecho", ECHOCTL, 0 }, { "-ctlecho", 0, ECHOCTL }, { "echoprt", ECHOPRT, 0 }, { "-echoprt", 0, ECHOPRT }, { "prterase", ECHOPRT, 0 }, { "-prterase", 0, ECHOPRT }, { "isig", ISIG, 0 }, { "-isig", 0, ISIG }, { "icanon", ICANON, 0 }, { "-icanon", 0, ICANON }, { "noflsh", NOFLSH, 0 }, { "-noflsh", 0, NOFLSH }, { "tostop", TOSTOP, 0 }, { "-tostop", 0, TOSTOP }, { "flusho", FLUSHO, 0 }, { "-flusho", 0, FLUSHO }, { "pendin", PENDIN, 0 }, { "-pendin", 0, PENDIN }, { "crt", ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT }, { "-crt", ECHOK, ECHOE|ECHOKE|ECHOCTL }, { "newcrt", ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT }, { "-newcrt", ECHOK, ECHOE|ECHOKE|ECHOCTL }, #ifdef XCASE { "xcase", XCASE, 0 }, { "-xcase", 0, XCASE }, #endif { NULL }, }; const struct modes omodes[] = { { "opost", OPOST, 0 }, { "-opost", 0, OPOST }, { "litout", 0, OPOST }, { "-litout", OPOST, 0 }, { "ocrnl", OCRNL, 0 }, { "-ocrnl", 0, OCRNL }, #ifdef OLCUC { "olcuc", OLCUC, 0 }, { "-olcuc", 0, OLCUC }, #endif { "onlcr", ONLCR, 0 }, { "-onlcr", 0, ONLCR }, { "onlret", ONLRET, 0 }, { "-onlret", 0, ONLRET }, { "onocr", ONOCR, 0 }, { "-onocr", 0, ONOCR }, { "tabs", 0, XTABS }, /* "preserve" tabs */ { "-tabs", XTABS, 0 }, { "oxtabs", XTABS, 0 }, { "-oxtabs", 0, XTABS }, { NULL }, }; #define CHK(s) (*name == s[0] && !strcmp(name, s)) int msearch(char ***argvp, struct info *ip) { const struct modes *mp; char *name; name = **argvp; for (mp = cmodes; mp->name; ++mp) if (CHK(mp->name)) { ip->t.c_cflag &= ~mp->unset; ip->t.c_cflag |= mp->set; ip->set = 1; return (1); } for (mp = imodes; mp->name; ++mp) if (CHK(mp->name)) { ip->t.c_iflag &= ~mp->unset; ip->t.c_iflag |= mp->set; ip->set = 1; return (1); } for (mp = lmodes; mp->name; ++mp) if (CHK(mp->name)) { ip->t.c_lflag &= ~mp->unset; ip->t.c_lflag |= mp->set; ip->set = 1; return (1); } for (mp = omodes; mp->name; ++mp) if (CHK(mp->name)) { ip->t.c_oflag &= ~mp->unset; ip->t.c_oflag |= mp->set; ip->set = 1; return (1); } return (0); } lpr-2008.05.17.3+nmu1/lpd/printjob.c0000644000000000000000000011401311013665313013367 0ustar /* $OpenBSD: printjob.c,v 1.44 2007/09/10 14:29:53 tobias Exp $ */ /* $NetBSD: printjob.c,v 1.31 2002/01/21 14:42:30 wiz Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static const char sccsid[] = "@(#)printjob.c 8.7 (Berkeley) 5/10/95"; #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 #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 pid_t child; /* pid of any filters */ static int lfd; /* lock file descriptor */ static int ofd; /* output filter file descriptor */ static pid_t ofilter; /* pid of output filter, if any */ static int pfd; /* prstatic inter file descriptor */ static pid_t pid; /* pid of lpd process */ static pid_t prchild; /* pid of pr process */ static char title[80]; /* ``pr'' title */ static int tof; /* true if at top of form */ static char class[32]; /* classification field */ static char fromhost[MAXHOSTNAMELEN]; /* user's host machine */ /* indentation size in static characters */ static char indent[10] = "-i0"; static char jobname[NAME_MAX]; /* job or file name */ static char length[10] = "-l"; /* page length in lines */ static char logname[LOGIN_NAME_MAX /*MAXLOGNAME*/]; /* 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[] = "errsXXXXXXXXXX"; /* file name for filter output */ static char width[10] = "-w"; /* page width in static characters */ static void abortpr(int); static void banner(char *, char *); static pid_t dofork(int); static int dropit(int); static void init(void); static void openpr(void); static void opennet(char *); static void opentty(void); static void openrem(void); static int print(int, char *); static int printit(char *); static void pstatus(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); static char response(void); static void scan_out(int, char *, int); static char *scnline(int, char *, int); static int sendfile(int, char *); static int sendit(char *); static void sendmail(char *, int); static void setty(void); static void alarmer(int); void printjob(void) { struct stat stb; struct queue *q, **qp; struct queue **queue; struct sigaction sa; int i, fd, nitems; off_t pidoff; int errcnt, count = 0; init(); /* set up capabilities */ (void)write(STDOUT_FILENO, "", 1); /* ack that daemon is started */ PRIV_START; fd = open(LF, O_WRONLY|O_APPEND, 0664); /* set up log file */ PRIV_END; if (fd < 0) { syslog(LOG_ERR, "%s: %m", LF); if ((fd = open(_PATH_DEVNULL, O_WRONLY)) < 0) exit(1); } if (fd != STDERR_FILENO) { if (dup2(fd, STDERR_FILENO) < 0) { syslog(LOG_ERR, "dup2: %m"); exit(1); } (void)close(fd); } pid = getpid(); /* for use with lprm */ setpgid(0, pid); /*setpgrp(0, pid);*/ /* we add SIGINT to the mask so abortpr() doesn't kill itself */ memset(&sa, 0, sizeof(sa)); sa.sa_handler = abortpr; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGINT); sigaction(SIGHUP, &sa, NULL); sigaction(SIGINT, &sa, NULL); sigaction(SIGQUIT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); /* so we can use short form file names */ if (chdir(SD) < 0) { syslog(LOG_ERR, "%s: %m", SD); exit(1); } (void)mktemp(tempfile); /* safe */ lfd = safe_open(LO, O_WRONLY|O_CREAT|O_NOFOLLOW/*|O_EXLOCK*/, 0640); if (lfd < 0 || flock(lfd,LOCK_EX|LOCK_NB)<0) { if (errno == EWOULDBLOCK) /* active daemon present */ exit(0); syslog(LOG_ERR, "%s: %s: %m", printer, LO); exit(1); } if (fstat(lfd, &stb) == 0 && (stb.st_mode & S_IXUSR)) exit(0); /* printing disabled */ ftruncate(lfd, 0); /* * write process id for others to know */ if ((pidoff = i = snprintf(line, sizeof(line), "%d\n", pid)) >= sizeof(line) || pidoff == -1) { syslog(LOG_ERR, "impossibly large pid: %u", pid); exit(1); } 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 & S_IXOTH) { /* reset queue flag */ stb.st_mode &= ~S_IXOTH; if (fchmod(lfd, stb.st_mode & 0777) < 0) syslog(LOG_ERR, "%s: %s: %m", printer, LO); } PRIV_START; openpr(); /* open printer or remote */ PRIV_END; 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(q)) { q = *qp++; if (stat(q->q_name, &stb) < 0) continue; errcnt = 0; restart: (void)lseek(lfd, pidoff, 0); if ((i = snprintf(line, sizeof(line), "%s\n", q->q_name)) >= sizeof(line) || i == -1) i = sizeof(line) - 1; /* can't happen */ 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 & S_IXUSR) goto done; /* rebuild queue (after lpc topq) */ if (stb.st_mode & S_IXOTH) { for (free(q); nitems--; free(q)) q = *qp++; stb.st_mode &= ~S_IXOTH; if (fchmod(lfd, stb.st_mode & 0777) < 0) syslog(LOG_WARNING, "%s: %s: %m", printer, LO); break; } } if (i == OK) /* file ok and printed */ count++; else if (i == REPRINT && ++errcnt < 5) { /* 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(NULL)) > 0 && i != ofilter) ; ofilter = 0; } (void)close(pfd); /* close printer */ if (ftruncate(lfd, pidoff) < 0) syslog(LOG_WARNING, "%s: %s: %m", printer, LO); PRIV_START; openpr(); /* try to reopen printer */ PRIV_END; goto restart; } else { syslog(LOG_WARNING, "%s: job could not be %s (%s)", printer, remote ? "sent to remote host" : "printed", q->q_name); if (i == REPRINT) { /* ensure we don't attempt this job again */ PRIV_START; (void)unlink(q->q_name); q->q_name[0] = 'd'; (void)unlink(q->q_name); PRIV_END; if (logname[0]) sendmail(logname, FATALERR); } } } free(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)close(ofd); (void)wait(NULL); (void)unlink(tempfile); exit(0); } goto again; } #define FONTLEN 50 char fonts[4][FONTLEN]; /* 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(char *file) { int i, fd; char *cp; int bombed = OK; /* * open control file; ignore if no longer there. */ fd = safe_open(file, O_RDONLY|O_NOFOLLOW, 0); if (fd < 0 || (cfp = fdopen(fd, "r")) == NULL) { syslog(LOG_INFO, "%s: %s: %m", printer, file); if (fd >= 0) (void)close(fd); return(OK); } /* * Reset troff fonts. */ for (i = 0; i < 4; i++) strlcpy(fonts[i], ifonts[i], FONTLEN); (void)snprintf(&width[2], sizeof(width) - 2, "%ld", PW); indent[2] = '0'; indent[3] = '\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 * R -- laser dpi "resolution" * 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 (getcfline(cfp)) switch (line[0]) { case 'H': strlcpy(fromhost, line+1, sizeof(fromhost)); if (class[0] == '\0') strlcpy(class, line+1, sizeof(class)); continue; case 'P': strlcpy(logname, line+1, sizeof(logname)); 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') strlcpy(jobname, line+1, sizeof(jobname)); else { jobname[0] = ' '; jobname[1] = '\0'; } continue; case 'C': if (line[1] != '\0') strlcpy(class, line+1, sizeof(class)); else if (class[0] == '\0') gethostname(class, sizeof(class)); continue; case 'T': /* header title for pr */ strlcpy(title, line+1, sizeof(title)); 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') strlcpy(fonts[line[0]-'1'], line+1, FONTLEN); continue; case 'W': /* page width */ strlcpy(width+2, line+1, sizeof(width) - 2); continue; case 'I': /* indent amount */ strlcpy(indent+2, line+1, sizeof(indent) - 2); 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': case 'R': continue; } /* pass 2 */ pass2: fseek(cfp, 0L, SEEK_SET); while (getcfline(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': if (strchr(line+1, '/')) continue; (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 occurred, * 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(int format, char *file) { ssize_t nread; struct stat stb; pid_t pid; char *prog, *av[17], buf[BUFSIZ]; int fd, status, serrno; int n, fi, fo, p[2], stopped = 0, nofile; PRIV_START; if (lstat(file, &stb) < 0 || (fi = safe_open(file, O_RDONLY, 0)) < 0) { PRIV_END; return(ERROR); } PRIV_END; /* * 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 (S_ISLNK(stb.st_mode) && 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' || format == 'o')) { 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] = "-f"; av[6] = NULL; 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 */ closelog(); nofile = sysconf(_SC_OPEN_MAX); for (n = 3; n < nofile; n++) (void)close(n); execl(_PATH_PR, "pr", width, length, "-f", "-h", *title ? title : " ", (char *)NULL); 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 'o': /* print postscript file */ /* * Treat this as a "plain file with control characters", and * assume the standard LPF_INPUT filter will recognize that * the data is postscript and know what to do with it. These * 'o'-file requests could come from MacOS 10.1 systems. * (later versions of MacOS 10 will explicitly use 'l') * A postscript file can contain binary data, which is why 'l' * is somewhat more appropriate than 'f'. */ /* FALLTHROUGH */ 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 = open(".railmag", O_CREAT|O_WRONLY|O_EXCL, 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 (prog == NULL) { (void)close(fi); syslog(LOG_ERR, "%s: no filter found in printcap for format character '%c'", printer, format); return(ERROR); } if ((av[0] = strrchr(prog, '/')) != NULL) av[0]++; else av[0] = prog; av[n++] = "-n"; av[n++] = logname; if (*jobname != '\0' && strcmp(jobname, " ") != 0) { av[n++] = "-j"; av[n++] = jobname; } 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 = waitpid((pid_t)-1, &status, WUNTRACED)) > 0 && pid != ofilter) ; if (WIFSTOPPED(status) == 0) { (void)close(fi); syslog(LOG_WARNING, "%s: output filter died (retcode=%d termsig=%d prog=%s)", printer, WEXITSTATUS(status), WTERMSIG(status), prog); return(REPRINT); } stopped++; } start: if ((child = dofork(DORETURN)) == 0) { /* child */ dup2(fi, 0); dup2(fo, 1); unlink(tempfile); n = open(tempfile, O_WRONLY|O_CREAT|O_EXCL, 0664); if (n >= 0) dup2(n, 2); closelog(); nofile = sysconf(_SC_OPEN_MAX); for (n = 3; n < nofile; n++) (void)close(n); execv(prog, av); syslog(LOG_ERR, "cannot execv %s", prog); _exit(2); } serrno = errno; (void)close(fi); errno = serrno; if (child < 0) { child = prchild = tof = 0; syslog(LOG_ERR, "cannot start child process: %m"); return (ERROR); } while ((pid = wait(&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 */ fd = safe_open(tempfile, O_RDONLY|O_NOFOLLOW, 0); if (fd >= 0) { while ((nread = read(fd, buf, sizeof(buf))) > 0) (void)write(STDERR_FILENO, buf, nread); (void)close(fd); } if (!WIFEXITED(status)) { syslog(LOG_WARNING, "%s: filter '%c' terminated (termsig=%d prog=%s)", printer, format, WTERMSIG(status), prog); return(ERROR); } switch (WEXITSTATUS(status)) { case 0: tof = 1; return(OK); case 1: return(REPRINT); case 2: return(ERROR); default: syslog(LOG_WARNING, "%s: filter '%c' exited (retcode=%d prog=%s)", printer, format, WEXITSTATUS(status), prog); return(FILTERERR); } } /* * Send the daemon control file (cf) and any data files. * Return -1 if a non-recoverable error occurred, 1 if a recoverable error and * 0 if all is well. */ static int sendit(char *file) { int fd, i, err = OK; char *cp, last[BUFSIZ]; /* open control file */ fd = safe_open(file, O_RDONLY|O_NOFOLLOW, 0); if (fd < 0 || (cfp = fdopen(fd, "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 (getcfline(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') { strlcpy(last, line, sizeof(last)); while ((i = getcfline(cfp)) != 0) 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, SEEK_SET); while (getcfline(cfp)) if (line[0] == 'U' && strchr(line+1, '/') == 0) (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(int type, char *file) { int f, i, amt; struct stat stb; char buf[BUFSIZ]; int sizerr, resp; PRIV_START; if (lstat(file, &stb) < 0 || (f = safe_open(file, O_RDONLY, 0)) < 0) { PRIV_END; return(ERROR); } PRIV_END; /* * 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 (S_ISLNK(stb.st_mode) && fstat(f, &stb) == 0 && (stb.st_dev != fdev || stb.st_ino != fino)) return(ACCESS); if ((amt = snprintf(buf, sizeof(buf), "%c%lld %s\n", type, (long long)stb.st_size, file)) >= sizeof(buf) || amt == -1) return (ACCESS); /* XXX hack */ 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) { struct sigaction osa, nsa; amt = BUFSIZ; if (i + amt > stb.st_size) amt = stb.st_size - i; if (sizerr == 0 && read(f, buf, amt) != amt) sizerr = 1; memset(&nsa, 0, sizeof(nsa)); nsa.sa_handler = alarmer; sigemptyset(&nsa.sa_mask); nsa.sa_flags = 0; (void)sigaction(SIGALRM, &nsa, &osa); alarm(wait_time); if (write(pfd, buf, amt) != amt) { alarm(0); (void)sigaction(SIGALRM, &osa, NULL); (void)close(f); return(REPRINT); } alarm(0); (void)sigaction(SIGALRM, &osa, NULL); } (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(void) { struct sigaction osa, nsa; char resp; memset(&nsa, 0, sizeof(nsa)); nsa.sa_handler = alarmer; sigemptyset(&nsa.sa_mask); nsa.sa_flags = 0; (void)sigaction(SIGALRM, &nsa, &osa); alarm(wait_time); if (read(pfd, &resp, 1) != 1) { syslog(LOG_INFO, "%s: lost connection", printer); resp = -1; } alarm(0); (void)sigaction(SIGALRM, &osa, NULL); return (resp); } /* * Banner printing stuff */ static void banner(char *name1, char *name2) { time_t tvec; 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\r", 2); } else { /* normal banner */ (void)write(ofd, "\n\r\n\r\n\r", 6); scan_out(ofd, name1, '\0'); (void)write(ofd, "\n\r\n\r", 4); scan_out(ofd, name2, '\0'); if (class[0]) { (void)write(ofd, "\n\r\n\r\n\r", 6); scan_out(ofd, class, '\0'); } (void)write(ofd, "\n\r\n\r\n\r\n\r\t\t\t\t\tJob: ", 19); (void)write(ofd, name2, strlen(name2)); (void)write(ofd, "\n\r\t\t\t\t\tDate: ", 13); (void)write(ofd, ctime(&tvec), 24); (void)write(ofd, "\n\r", 2); } if (!SF) (void)write(ofd, FF, strlen(FF)); tof = 1; } static char * scnline(int key, char *p, int c) { int scnwidth; for (scnwidth = WIDTH; --scnwidth;) { key <<= 1; *p++ = key & 0200 ? c : BACKGND; } return (p); } #define TRC(q) (((q)-' ')&0177) static void scan_out(int scfd, char *scsp, int dlm) { char *strp; int nchrs, j; char outbuf[LINELEN+2], *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[(int)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'; *strp++ = '\r'; (void)write(scfd, outbuf, strp-outbuf); } } static int dropit(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(char *user, int bombed) { int i, p[2], s, nofile; char *cp = NULL; struct stat stb; FILE *fp; if (user[0] == '-' || user[0] == '/' || !isprint(user[0])) return; pipe(p); if ((s = dofork(DORETURN)) == 0) { /* child */ dup2(p[0], 0); closelog(); nofile = sysconf(_SC_OPEN_MAX); for (i = 3; i < nofile; i++) (void)close(i); if ((cp = strrchr(_PATH_SENDMAIL, '/')) != NULL) cp++; else cp = _PATH_SENDMAIL; execl(_PATH_SENDMAIL, cp, "-t", (char *)NULL); _exit(0); } else if (s > 0) { /* parent */ dup2(p[1], 1); printf("Auto-Submitted: auto-generated\n"); printf("To: %s@%s\n", user, fromhost); printf("Subject: %s printer job \"%s\"\n", printer, *jobname ? jobname : ""); printf("Reply-To: root@%s\n\n", host); printf("Your printer job "); if (*jobname) printf("(%s) ", jobname); switch (bombed) { case OK: printf("\ncompleted successfully\n"); cp = "OK"; break; default: case FATALERR: printf("\ncould not be printed\n"); cp = "FATALERR"; break; case NOACCT: printf("\ncould not be printed without an account on %s\n", host); cp = "NOACCT"; break; case FILTERERR: if (stat(tempfile, &stb) < 0 || stb.st_size == 0 || (fp = fopen(tempfile, "r")) == NULL) { printf("\nhad some errors and may not have printed\n"); break; } printf("\nhad the following errors and may not have printed:\n"); while ((i = getc(fp)) != EOF) putchar(i); (void)fclose(fp); cp = "FILTERERR"; break; case ACCESS: printf("\nwas not printed because it was not linked to the original file\n"); cp = "ACCESS"; } fflush(stdout); (void)close(1); } else { syslog(LOG_ERR, "fork for sendmail failed: %m"); } (void)close(p[0]); (void)close(p[1]); if (s != -1) { wait(NULL); syslog(LOG_INFO, "mail sent to user %s about job %s on printer %s (%s)", user, *jobname ? jobname : "", printer, cp); } } /* * dofork - fork with retries on failure */ static pid_t dofork(int action) { struct passwd *pw; pid_t pid; int i; 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) { (void)close(lfd); PRIV_START; pw = getpwuid(DU); if (pw == 0) { syslog(LOG_ERR, "uid %ld not in password file", DU); break; } initgroups(pw->pw_name, pw->pw_gid); setgid(pw->pw_gid); 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(int signo) { (void)close(lfd); (void)unlink(tempfile); (void)kill(0, SIGINT); if (ofilter > 0) kill(ofilter, SIGCONT); while (wait(NULL) > 0) ; _exit(0); } static void init(void) { int status; char *s; PRIV_START; status = cgetent(&bp, printcapdb, printer); PRIV_END; switch (status) { case -1: syslog(LOG_ERR, "unknown printer: %s", printer); exit(1); case -2: syslog(LOG_ERR, "can't open printer description file"); exit(1); case -3: fatal("potential reference loop detected in printcap file"); default: break; } if (cgetstr(bp, DEFLP, &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 = DEFNUID; if (cgetstr(bp, "ff", &FF) == -1) FF = DEFFF; if (cgetnum(bp, "pw", &PW) < 0) PW = DEFWIDTH; (void)snprintf(&width[2], sizeof(width) - 2, "%ld", PW); if (cgetnum(bp, "pl", &PL) < 0) PL = DEFLENGTH; (void)snprintf(&length[2], sizeof(length) - 2, "%ld", PL); if (cgetnum(bp, "px", &PX) < 0) PX = 0; (void)snprintf(&pxwidth[2], sizeof(pxwidth) - 2, "%ld", PX); if (cgetnum(bp, "py", &PY) < 0) PY = 0; (void)snprintf(&pxlength[2], sizeof(pxlength) - 2, "%ld", PY); cgetstr(bp, "rm", &RM); if ((s = checkremote()) != NULL) syslog(LOG_WARNING, "%s", 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; cgetstr(bp, "ms", &MS); tof = (cgetcap(bp, "fo", ':') == NULL); } /* * Acquire line printer or remote connection. * XXX - should push down privs in here */ static void openpr(void) { int i, nofile; char *cp; extern int rflag; if (!remote && *LP) { if ((cp = strchr(LP, '@'))) opennet(cp); else opentty(); } else if (remote) { openrem(); } else { syslog(LOG_ERR, "%s: no line printer device or host name", printer); exit(1); } /* * Start up an output filter, if needed. */ if ((!remote || rflag) && OF) { int p[2]; pipe(p); if ((ofilter = dofork(DOABORT)) == 0) { /* child */ dup2(p[0], 0); /* pipe is std in */ dup2(pfd, 1); /* printer is std out */ closelog(); nofile = sysconf(_SC_OPEN_MAX); for (i = 3; i < nofile; i++) (void)close(i); if ((cp = strrchr(OF, '/')) == NULL) cp = OF; else cp++; execl(OF, cp, width, length, (char *)NULL); 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; } } /* * Printer connected directly to the network * or to a terminal server on the net */ static void opennet(char *cp) { int i; int resp, port; char save_ch; save_ch = *cp; *cp = '\0'; port = atoi(LP); if (port <= 0) { syslog(LOG_ERR, "%s: bad port number: %s", printer, LP); exit(1); } *cp++ = save_ch; for (i = 1; ; i = i < 256 ? i << 1 : i) { resp = -1; pfd = getport(cp, port); if (pfd < 0 && errno == ECONNREFUSED) resp = 1; else if (pfd >= 0) { /* * need to delay a bit for rs232 lines * to stabilize in case printer is * connected via a terminal server */ delay(500); break; } if (i == 1) { if (resp < 0) pstatus("waiting for %s to come up", LP); else pstatus("waiting for access to printer on %s", LP); } sleep(i); } pstatus("sending to %s port %d", cp, port); } /* * Printer is connected to an RS232 port on this host */ static void opentty(void) { int i; for (i = 1; ; i = i < 32 ? i << 1 : i) { pfd = open(LP, RW ? O_RDWR : O_WRONLY); if (pfd >= 0) { delay(500); 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); } /* * Printer is on a remote host */ static void openrem(void) { int i, n; int resp; for (i = 1; ; i = i < 256 ? i << 1 : i) { resp = -1; pfd = getport(RM, 0); if (pfd >= 0) { if ((n = snprintf(line, sizeof(line), "\2%s\n", RP)) >= sizeof(line) || n == -1) n = sizeof(line) - 1; 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); } static void alarmer(int s) { /* nothing */ } #if !defined(__NetBSD__) && !defined(__OpenBSD__) 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, B19200}, {38400, B38400}, {57600, B57600}, {115200, B115200}, {0, 0} }; #endif /* * setup tty lines. */ static void setty(void) { struct info i; char **argv, **ap, **ep, *p, *val; i.fd = pfd; i.set = i.wset = 0; if (ioctl(i.fd, TIOCEXCL, (char *)0) < 0) { syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer); exit(1); } if (tcgetattr(i.fd, &i.t) < 0) { syslog(LOG_ERR, "%s: tcgetattr: %m", printer); exit(1); } if (BR > 0) { #if defined(__NetBSD__) || defined(__OpenBSD__) cfsetspeed(&i.t, BR); #else struct bauds *bp; for (bp = bauds; bp->baud; bp++) if (BR == bp->baud) break; if (!bp->baud) { syslog(LOG_ERR, "%s: illegal baud rate %d", printer, (int)BR); exit(1); } cfsetspeed(&i.t, bp->speed); #endif i.set = 1; } if (MS) { if (ioctl(i.fd, TIOCGETD, &i.ldisc) < 0) { syslog(LOG_ERR, "%s: ioctl(TIOCGETD): %m", printer); exit(1); } if (ioctl(i.fd, TIOCGWINSZ, &i.win) < 0) syslog(LOG_INFO, "%s: ioctl(TIOCGWINSZ): %m", printer); argv = (char **)calloc(256, sizeof(char *)); if (argv == NULL) { syslog(LOG_ERR, "%s: malloc: %m", printer); exit(1); } p = strdup(MS); ap = argv; ep = argv + 255; while ((val = strsep(&p, " \t,")) != NULL) { if ((*ap++ = strdup(val)) == NULL) { syslog(LOG_ERR, "%s: strdup: %m", printer); exit(1); } if (ap == ep) { syslog(LOG_ERR, "%s: too many \"ms\" entries", printer); exit(1); } } *ap = NULL; for (; *argv; ++argv) { if (ksearch(&argv, &i)) continue; if (msearch(&argv, &i)) continue; syslog(LOG_INFO, "%s: unknown stty flag: %s", printer, *argv); } } else { if (FC) { i.t.c_cflag &= ~FC; i.set = 1; } if (FS) { i.t.c_cflag |= FS; i.set = 1; } if (XC) { i.t.c_lflag &= ~XC; i.set = 1; } if (XS) { i.t.c_lflag |= XS; i.set = 1; } } if (i.set && tcsetattr(i.fd, TCSANOW, &i.t) < 0) { syslog(LOG_ERR, "%s: tcsetattr: %m", printer); exit(1); } if (i.wset && ioctl(i.fd, TIOCSWINSZ, &i.win) < 0) syslog(LOG_INFO, "%s: ioctl(TIOCSWINSZ): %m", printer); return; } static void pstatus(const char *msg, ...) { int fd, len; char buf[BUFSIZ]; va_list ap; va_start(ap, msg); umask(0); fd = open(ST, O_WRONLY|O_CREAT|O_NOFOLLOW /*|O_EXLOCK*/, 0660); if (fd < 0 || flock(fd,LOCK_EX|LOCK_NB)<0) { syslog(LOG_ERR, "%s: %s: %m", printer, ST); exit(1); } ftruncate(fd, 0); len = vsnprintf(buf, sizeof(buf), msg, ap); va_end(ap); if (len < 0) /* Output error */ return; if (len >= sizeof(buf)) len = sizeof(buf) - 1; buf[len++] = '\n'; /* replace NUL with newline */ (void)write(fd, buf, len); (void)close(fd); } lpr-2008.05.17.3+nmu1/lpd/rcmd.c0000644000000000000000000002074011014376340012470 0ustar /* ***** NOTE: Parts of this file are from src/lib/libc/net/rcmd.c. The entire file is NOT included. ***** * Copyright (c) 1995, 1996, 1998 Theo de Raadt. All rights reserved. * 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. 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #include // int __ivaliduser(FILE *, in_addr_t, const char *, const char *); int __ivaliduser_sa(FILE *, struct sockaddr *, socklen_t, const char *, const char *); static int __icheckhost(struct sockaddr *, socklen_t, const char *); static char *__gethostloop(struct sockaddr *, socklen_t); /* * XXX * Don't make static, used by lpd(8). * * Returns 0 if ok, -1 if not ok. */ /* int __ivaliduser(hostf, raddrl, luser, ruser) FILE *hostf; in_addr_t raddrl; const char *luser, *ruser; { struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_len = sizeof(struct sockaddr_in); memcpy(&sin.sin_addr, &raddrl, sizeof(sin.sin_addr)); return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len, luser, ruser); }*/ int __ivaliduser_sa(FILE *hostf, struct sockaddr *raddr, socklen_t salen, const char *luser, const char *ruser) { register char *user, *p; char *buf; const char *auser, *ahost; int hostok, userok; char *rhost = (char *)-1; char domain[MAXHOSTNAMELEN]; #define BUFFER_SIZE 2048 size_t buflen; char buffer[BUFFER_SIZE]; getdomainname(domain, sizeof(domain)); while ((buf = fgets(buffer, BUFFER_SIZE, hostf))) { buflen = strlen( buffer ); /* Fix for the case where buffer[strlen(buffer)-1] != "\n" for cases where the hosts.lpd or hosts.equiv doesn't end in a newline */ if( buflen+1 < BUFFER_SIZE && buffer[buflen-1] != '\n' ) { buffer[buflen] = '\n'; buffer[buflen+1] = '\0'; buflen++; } p = buf; if (*p == '#') continue; while (p < buf + buflen && *p != '\n' && *p != ' ' && *p != '\t') { if (!isprint(*p)) goto bail; *p = isupper(*p) ? tolower(*p) : *p; p++; } if (p >= buf + buflen) continue; if (*p == ' ' || *p == '\t') { *p++ = '\0'; while (p < buf + buflen && (*p == ' ' || *p == '\t')) p++; if (p >= buf + buflen) continue; user = p; while (p < buf + buflen && *p != '\n' && *p != ' ' && *p != '\t') { if (!isprint(*p)) goto bail; p++; } } else user = p; *p = '\0'; if (p == buf) continue; auser = *user ? user : luser; ahost = buf; if (strlen(ahost) >= MAXHOSTNAMELEN) continue; /* * innetgr() must lookup a hostname (we do not attempt * to change the semantics so that netgroups may have * #.#.#.# addresses in the list.) */ if (ahost[0] == '+') switch (ahost[1]) { case '\0': hostok = 1; break; case '@': if (rhost == (char *)-1) rhost = __gethostloop(raddr, salen); hostok = 0; if (rhost) hostok = innetgr(&ahost[2], rhost, NULL, domain); break; default: hostok = __icheckhost(raddr, salen, &ahost[1]); break; } else if (ahost[0] == '-') switch (ahost[1]) { case '\0': hostok = -1; break; case '@': if (rhost == (char *)-1) rhost = __gethostloop(raddr, salen); hostok = 0; if (rhost) hostok = -innetgr(&ahost[2], rhost, NULL, domain); break; default: hostok = -__icheckhost(raddr, salen, &ahost[1]); break; } else hostok = __icheckhost(raddr, salen, ahost); if (auser[0] == '+') switch (auser[1]) { case '\0': userok = 1; break; case '@': userok = innetgr(&auser[2], NULL, ruser, domain); break; default: userok = strcmp(ruser, &auser[1]) ? 0 : 1; break; } else if (auser[0] == '-') switch (auser[1]) { case '\0': userok = -1; break; case '@': userok = -innetgr(&auser[2], NULL, ruser, domain); break; default: userok = strcmp(ruser, &auser[1]) ? 0 : -1; break; } else userok = strcmp(ruser, auser) ? 0 : 1; /* Check if one component did not match */ if (hostok == 0 || userok == 0) continue; /* Check if we got a forbidden pair */ if (userok <= -1 || hostok <= -1) return (-1); /* Check if we got a valid pair */ if (hostok >= 1 && userok >= 1) return (0); } bail: return (-1); } /* * Returns "true" if match, 0 if no match. If we do not find any * semblance of an A->PTR->A loop, allow a simple #.#.#.# match to work. */ static int __icheckhost(struct sockaddr *raddr, socklen_t salen, const char *lhost) { struct addrinfo hints, *res, *r; char h1[NI_MAXHOST], h2[NI_MAXHOST]; int error; const int niflags = NI_NUMERICHOST; h1[0] = '\0'; if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0, niflags) != 0) return (0); /* Resolve laddr into sockaddr */ memset(&hints, 0, sizeof(hints)); hints.ai_family = raddr->sa_family; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ res = NULL; error = getaddrinfo(lhost, "0", &hints, &res); if (error) return (0); /* * Try string comparisons between raddr and laddr. */ for (r = res; r; r = r->ai_next) { h2[0] = '\0'; if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2), NULL, 0, niflags) != 0) continue; if (strcmp(h1, h2) == 0) { freeaddrinfo(res); return (1); } } /* No match. */ freeaddrinfo(res); return (0); } /* * Return the hostname associated with the supplied address. * Do a reverse lookup as well for security. If a loop cannot * be found, pack the result of inet_ntoa() into the string. */ static char * __gethostloop(struct sockaddr *raddr, socklen_t salen) { static char remotehost[NI_MAXHOST]; char h1[NI_MAXHOST], h2[NI_MAXHOST]; struct addrinfo hints, *res, *r; int error; const int niflags = NI_NUMERICHOST; h1[0] = remotehost[0] = '\0'; if (getnameinfo(raddr, salen, remotehost, sizeof(remotehost), NULL, 0, NI_NAMEREQD) != 0) return (NULL); if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0, niflags) != 0) return (NULL); /* * Look up the name and check that the supplied * address is in the list */ memset(&hints, 0, sizeof(hints)); hints.ai_family = raddr->sa_family; hints.ai_socktype = SOCK_DGRAM; /*dummy*/ hints.ai_flags = AI_CANONNAME; res = NULL; error = getaddrinfo(remotehost, "0", &hints, &res); if (error) return (NULL); for (r = res; r; r = r->ai_next) { h2[0] = '\0'; if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2), NULL, 0, niflags) != 0) continue; if (strcmp(h1, h2) == 0) { freeaddrinfo(res); return (remotehost); } } /* * either the DNS adminstrator has made a configuration * mistake, or someone has attempted to spoof us */ syslog(LOG_NOTICE, "rcmd: address %s not listed for host %s", h1, res->ai_canonname ? res->ai_canonname : remotehost); freeaddrinfo(res); return (NULL); } lpr-2008.05.17.3+nmu1/lpd/recvjob.c0000644000000000000000000002155412433532572013210 0ustar /* $OpenBSD: recvjob.c,v 1.24 2008/09/02 00:14:23 deraadt Exp $ */ /* $NetBSD: recvjob.c,v 1.14 2001/12/04 22:52:44 christos Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static const char sccsid[] = "@(#)recvjob.c 8.2 (Berkeley) 4/27/95"; #else static const char rcsid[] = "$OpenBSD: recvjob.c,v 1.24 2008/09/02 00:14:23 deraadt Exp $"; #endif #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 #include #include #include "lp.h" #include "lp.local.h" #include "extern.h" #include "pathnames.h" #define ack() (void)write(STDOUT_FILENO, sp, 1); static char dfname[NAME_MAX]; /* data files */ static int minfree; /* keep at least minfree blocks available */ static char *sp = ""; static char tfname[NAME_MAX]; /* tmp copy of cf before linking */ static int chksize(int); static void frecverr(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); static int noresponse(void); static void rcleanup(int); static int read_number(char *); static int readfile(char *, int); static int readjob(void); void recvjob(void) { 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 */ PRIV_START; if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) { syslog(LOG_ERR, "%s: %m", LF); (void)open(_PATH_DEVNULL, O_WRONLY); } PRIV_END; 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 transferred. */ static int readjob(void) { int size, nfiles; char *cp; ack(); nfiles = 0; for (;;) { /* * Read a command to tell us what to do */ cp = line; do { if ((size = read(STDOUT_FILENO, cp, 1)) != 1) { if (size < 0) frecverr("%s: Lost connection", printer); return(nfiles); } } while (*cp++ != '\n' && (cp - line + 1) < sizeof(line)); if (cp - line + 1 >= sizeof(line)) frecverr("readjob overflow"); *--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 */ strlcpy(cp + 6, from, sizeof(line) + line - cp - 6); if (strchr(cp, '/')) frecverr("readjob: %s: illegal path name", cp); strlcpy(tfname, cp, sizeof(tfname)); tfname[0] = 't'; if (!chksize(size)) { (void)write(STDOUT_FILENO, "\2", 1); continue; } /* * XXX * We blindly believe what the remote host puts * for the path to the df file. In general this * is OK since we don't allow paths with '/' in * them. Still, it would be better to sanity * check the cf file sent to us and make the * df name match the cf name we used. That way * we avoid any possible collisions. */ if (!readfile(tfname, size)) { rcleanup(0); continue; } if (link(tfname, cp) < 0) frecverr("link %s %s: %m", tfname, cp); (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 (strchr(cp, '/')) frecverr("readjob: %s: illegal path name", cp); if (!chksize(size)) { (void)write(STDOUT_FILENO, "\2", 1); continue; } (void)strlcpy(dfname, cp, sizeof(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(char *file, int size) { char *cp; char buf[BUFSIZ]; int i, j, amt; int fd, err; if ((fd = open(file, O_CREAT|O_EXCL|O_WRONLY, FILMOD)) < 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(STDOUT_FILENO, 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 */ if (strchr(file, '/') == NULL) (void)unlink(file); return(0); } ack(); return(1); } static int noresponse(void) { char resp; if (read(STDOUT_FILENO, &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(int size) { int64_t spacefree; struct statfs sfb; if (size <= 0) return (0); 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(char *fn) { char lin[80]; FILE *fp; if ((fp = fopen(fn, "r")) == NULL) return (0); if (fgets(lin, sizeof(lin), fp) == NULL) { fclose(fp); return (0); } fclose(fp); return (atoi(lin)); } /* * Remove all the files associated with the current job being transferred. */ static void rcleanup(int signo) { int save_errno = errno; if (tfname[0] && strchr(tfname, '/') == NULL) (void)unlink(tfname); if (dfname[0] && strchr(dfname, '/') == NULL) { do { do (void)unlink(dfname); while (dfname[2]-- != 'A') ; dfname[2] = 'z'; } while (dfname[0]-- != 'd'); } dfname[0] = '\0'; errno = save_errno; } static void frecverr(const char *msg, ...) { extern char fromb[]; va_list ap; va_start(ap, msg); rcleanup(0); syslog(LOG_ERR, "%s", fromb); vsyslog(LOG_ERR, msg, ap); va_end(ap); putchar('\1'); /* return error code */ exit(1); } lpr-2008.05.17.3+nmu1/lpd/ttcompat.c0000644000000000000000000001636307666757625013437 0ustar /* $OpenBSD: ttcompat.c,v 1.6 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: ttcompat.c,v 1.9 1995/11/15 22:50:00 pk Exp $ */ /* * Copyright (c) 1995 * 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. 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. */ /* * ttcompat.c -- convert sgtty flags to termios * originally from /sys/kern/tty_compat.c */ #ifndef lint static const char rcsid[] = "$OpenBSD: ttcompat.c,v 1.6 2003/06/02 23:36:53 millert Exp $"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include "extern.h" /* Macros to clear/set/test flags. */ #define SET(t, f) (t) |= (f) #define CLR(t, f) (t) &= ~(f) #define ISSET(t, f) ((t) & (f)) static int sttygetoflags(struct termios *); static void sttysetoflags(struct termios *, int); static int sttygetoflags(struct termios *tp) { tcflag_t iflag = tp->c_iflag; tcflag_t lflag = tp->c_lflag; tcflag_t oflag = tp->c_oflag; tcflag_t cflag = tp->c_cflag; int flags = 0; if (ISSET(cflag, PARENB)) { if (ISSET(iflag, INPCK)) { if (ISSET(cflag, PARODD)) SET(flags, ODDP); else SET(flags, EVENP); } else SET(flags, EVENP|ODDP); } if (ISSET(cflag, CSIZE) == CS8) { if (!ISSET(iflag, ISTRIP)) SET(flags, PASS8); if (!ISSET(oflag, OPOST)) SET(flags, LITOUT); } if (ISSET(lflag, XCASE)) SET(flags, LCASE); if (!ISSET(lflag, ICANON)) { /* fudge */ if (ISSET(iflag, IXON) || ISSET(lflag, ISIG|IEXTEN) || ISSET(cflag, PARENB)) SET(flags, CBREAK); else SET(flags, RAW); } return (flags); } static void sttysetoflags(struct termios *tp, int flags) { tcflag_t iflag = tp->c_iflag; tcflag_t oflag = tp->c_oflag; tcflag_t lflag = tp->c_lflag; tcflag_t cflag = tp->c_cflag; if (ISSET(flags, RAW)) { iflag &= IXOFF; CLR(lflag, ISIG|ICANON|IEXTEN|XCASE); CLR(cflag, PARENB); } else { SET(iflag, BRKINT|IXON|IMAXBEL); SET(lflag, ISIG|IEXTEN); if (ISSET(flags, CBREAK)) CLR(lflag, ICANON); else SET(lflag, ICANON); if (ISSET(iflag, IUCLC) && ISSET(oflag, OLCUC)) SET(lflag, XCASE); switch (ISSET(flags, ANYP)) { case 0: CLR(cflag, PARENB); break; case ANYP: SET(cflag, PARENB); CLR(iflag, INPCK); break; case EVENP: SET(cflag, PARENB); SET(iflag, INPCK); CLR(cflag, PARODD); break; case ODDP: SET(cflag, PARENB); SET(iflag, INPCK); SET(cflag, PARODD); break; } } if (ISSET(flags, RAW|LITOUT|PASS8)) { CLR(cflag, CSIZE); SET(cflag, CS8); if (!ISSET(flags, RAW|PASS8)) SET(iflag, ISTRIP); else CLR(iflag, ISTRIP); if (!ISSET(flags, RAW|LITOUT)) SET(oflag, OPOST); else CLR(oflag, OPOST); } else { CLR(cflag, CSIZE); SET(cflag, CS7); SET(iflag, ISTRIP); SET(oflag, OPOST); } tp->c_iflag = iflag; tp->c_oflag = oflag; tp->c_lflag = lflag; tp->c_cflag = cflag; } void sttyclearflags(struct termios *tp, int flags) { tcflag_t iflag = tp->c_iflag; tcflag_t oflag = tp->c_oflag; tcflag_t lflag = tp->c_lflag; tcflag_t cflag = tp->c_cflag; int oflags = sttygetoflags(tp) & ~flags; if (ISSET(flags, TANDEM)) CLR(iflag, IXOFF); if (ISSET(flags, ECHO)) CLR(lflag, ECHO); if (ISSET(flags, CRMOD)) { CLR(iflag, ICRNL); CLR(oflag, ONLCR); } if (ISSET(flags, LCASE)) { CLR(iflag, IUCLC); CLR(oflag, OLCUC); CLR(lflag, XCASE); } if (ISSET(flags, XTABS)) CLR(oflag, OXTABS); tp->c_iflag = iflag; tp->c_oflag = oflag; tp->c_lflag = lflag; tp->c_cflag = cflag; sttysetoflags(tp, oflags); } void sttysetflags(struct termios *tp, int flags) { tcflag_t iflag = tp->c_iflag; tcflag_t oflag = tp->c_oflag; tcflag_t lflag = tp->c_lflag; tcflag_t cflag = tp->c_cflag; int oflags = sttygetoflags(tp) | flags; if (ISSET(flags, TANDEM)) SET(iflag, IXOFF); if (ISSET(flags, ECHO)) SET(lflag, ECHO); if (ISSET(flags, CRMOD)) { SET(iflag, ICRNL); SET(oflag, ONLCR); } if (ISSET(flags, LCASE)) { SET(iflag, IUCLC); SET(oflag, OLCUC); SET(lflag, XCASE); } if (ISSET(flags, XTABS)) SET(oflag, OXTABS); tp->c_iflag = iflag; tp->c_oflag = oflag; tp->c_lflag = lflag; tp->c_cflag = cflag; sttysetoflags(tp, oflags); } void sttyclearlflags(struct termios *tp, int flags) { tcflag_t iflag = tp->c_iflag; tcflag_t oflag = tp->c_oflag; tcflag_t lflag = tp->c_lflag; tcflag_t cflag = tp->c_cflag; int oflags = sttygetoflags(tp) & ~flags; /* Nothing we can do with CRTBS. */ if (ISSET(flags, PRTERA)) CLR(lflag, ECHOPRT); if (ISSET(flags, CRTERA)) CLR(lflag, ECHOE); /* Nothing we can do with TILDE. */ if (ISSET(flags, MDMBUF)) CLR(cflag, MDMBUF); if (ISSET(flags, NOHANG)) SET(cflag, HUPCL); if (ISSET(flags, CRTKIL)) CLR(lflag, ECHOKE); if (ISSET(flags, CTLECH)) CLR(lflag, ECHOCTL); if (ISSET(flags, DECCTQ)) SET(iflag, IXANY); CLR(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH)); tp->c_iflag = iflag; tp->c_oflag = oflag; tp->c_lflag = lflag; tp->c_cflag = cflag; sttysetoflags(tp, oflags); } void sttysetlflags(struct termios *tp, int flags) { tcflag_t iflag = tp->c_iflag; tcflag_t oflag = tp->c_oflag; tcflag_t lflag = tp->c_lflag; tcflag_t cflag = tp->c_cflag; int oflags = sttygetoflags(tp) | flags; /* Nothing we can do with CRTBS. */ if (ISSET(flags, PRTERA)) SET(lflag, ECHOPRT); if (ISSET(flags, CRTERA)) SET(lflag, ECHOE); /* Nothing we can do with TILDE. */ if (ISSET(flags, MDMBUF)) SET(cflag, MDMBUF); if (ISSET(flags, NOHANG)) CLR(cflag, HUPCL); if (ISSET(flags, CRTKIL)) SET(lflag, ECHOKE); if (ISSET(flags, CTLECH)) SET(lflag, ECHOCTL); if (ISSET(flags, DECCTQ)) CLR(iflag, IXANY); SET(lflag, ISSET(flags, TOSTOP|FLUSHO|PENDIN|NOFLSH)); tp->c_iflag = iflag; tp->c_oflag = oflag; tp->c_lflag = lflag; tp->c_cflag = cflag; sttysetoflags(tp, oflags); } lpr-2008.05.17.3+nmu1/lpq/0000755000000000000000000000000013416173536011423 5ustar lpr-2008.05.17.3+nmu1/lpq/Makefile0000644000000000000000000000056310176611664013066 0ustar # from: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $OpenBSD: Makefile,v 1.4 2002/06/08 01:53:43 millert Exp $ PROG= lpq CFLAGS+=-I${.CURDIR}/../common_source SRCS= lpq.c ../common_source/displayq.c ../common_source/common.c \ ../common_source/common_vars.c ../common_source/getcap.c ../common_source/vis.c BINGRP= daemon BINMODE=2555 BINDIR= /usr/bin include ../Makefile.in lpr-2008.05.17.3+nmu1/lpq/lpq.10000644000000000000000000001065511013660143012272 0ustar .\" $OpenBSD: lpq.1,v 1.10 2007/05/31 19:20:25 jmc Exp $ .\" $NetBSD: lpq.1,v 1.11 2002/01/19 03:23:11 wiz Exp $ .\" .\" 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. 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.2 (Berkeley) 4/28/95 .\" .Dd $Mdocdate: May 31 2007 $ .Dt LPQ 1 .Os .Sh NAME .Nm lpq .Nd spool queue examination program .Sh SYNOPSIS .Nm lpq .Op Fl al .Op Fl P Ns Ar printer .Op Ar job# Ar ... .Op Ar user Ar ... .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 invoked without any arguments reports on any jobs currently in the queue. .Pp The options are as follows: .Bl -tag -width Ds .It Fl a Report on the local queues for all printers, rather than just the specified printer. .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. .It Fl P Ns Ar printer 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. .El .Pp For each job submitted (i.e., invocation of .Xr lpr 1 ) .Nm 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 .Dq (standard input) . .Pp If .Nm 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 "/var/spool/output/*/lock" -compact .It Pa /etc/printcap To determine printer characteristics. .It Pa /var/spool/* The spooling directory, as determined from printcap. .It Pa /var/spool/output/*/cf* Control files specifying jobs. .It Pa /var/spool/output/*/lock The lock file to obtain the currently active job. .El .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. .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 may report unreliably. Output formatting is sensitive to the line length of the terminal; this can result in widely spaced columns. lpr-2008.05.17.3+nmu1/lpq/lpq.c0000644000000000000000000001206111013670040012342 0ustar /* $OpenBSD: lpq.c,v 1.16 2007/02/16 13:29:04 jmc Exp $ */ /* $NetBSD: lpq.c,v 1.9 1999/12/07 14:54:47 mrg Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static const char sccsid[] = "@(#)lpq.c 8.3 (Berkeley) 5/10/95"; #else static const char rcsid[] = "$OpenBSD: lpq.c,v 1.16 2007/02/16 13:29:04 jmc Exp $"; #endif #endif /* not lint */ /* * Spool Queue examination program * * lpq [-a] [-l] [-Pprinter] [user...] [job...] * * -a show all non-null queues on the local machine * -l long output * -P used to identify printer as per lpr/lprm */ #include #include #include #include #include #include #include #include #include #include #include "lp.h" #include "lp.local.h" #include "pathnames.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 */ volatile sig_atomic_t gotintr; static int ckqueue(char *); static void usage(void); int main(int argc, char **argv) { int ch, aflag, lflag; char *buf, *cp; long l; effective_uid = geteuid(); real_uid = getuid(); effective_gid = getegid(); real_gid = getgid(); PRIV_END; /* be safe */ if (gethostname(host, sizeof(host)) != 0) err(1, "gethostname"); openlog("lpq", 0, LOG_LPR); aflag = lflag = 0; while ((ch = getopt(argc, argv, "alP:w:")) != -1) { switch(ch) { case 'a': ++aflag; break; case 'l': /* long output */ ++lflag; break; case 'P': /* printer name */ printer = optarg; break; case 'w': l = strtol(optarg, &cp, 10); if (*cp != '\0' || l < 0 || l >= INT_MAX) errx(1, "wait time must be postive integer: %s", optarg); wait_time = (u_int)l; if (wait_time < 30) warnx("warning: wait time less than 30 seconds"); break; default: usage(); } } if (!aflag && 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; } if (aflag) { while (cgetnext(&buf, printcapdb) > 0) { if (ckqueue(buf) <= 0) { free(buf); continue; /* no jobs */ } for (cp = buf; *cp; cp++) if (*cp == '|' || *cp == ':') { *cp = '\0'; break; } printer = buf; printf("%s:\n", printer); displayq(lflag); free(buf); printf("\n"); } } else displayq(lflag); exit(0); } /* XXX - could be common w/ lpd */ static int ckqueue(char *cap) { struct dirent *d; DIR *dirp; char *spooldir; int free_spooldir = 1; if (cgetstr(cap, "sd", &spooldir) == -1){ spooldir = _PATH_DEFSPOOL; free_spooldir = 0; } dirp = opendir(spooldir); if (free_spooldir) free(spooldir); if (dirp == NULL) return (-1); while ((d = readdir(dirp)) != NULL) { if (d->d_name[0] != 'c' || d->d_name[1] != 'f') continue; /* daemon control files only */ closedir(dirp); return (1); /* found something */ } closedir(dirp); return (0); } static void usage(void) { extern char *__progname; fprintf(stderr, "usage: %s [-al] [-Pprinter] [job# ...] [user ...]\n", __progname); exit(1); } lpr-2008.05.17.3+nmu1/lpr/0000755000000000000000000000000013416173536011424 5ustar lpr-2008.05.17.3+nmu1/lpr/Makefile0000644000000000000000000000055710176611664013072 0ustar # from: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $OpenBSD: Makefile,v 1.5 2003/03/11 04:36:55 millert Exp $ PROG= lpr CFLAGS+=-I${.CURDIR}/../common_source -g SRCS= lpr.c ../common_source/startdaemon.c ../common_source/common.c \ ../common_source/common_vars.c ../common_source/getcap.c BINOWN= root BINGRP= daemon BINMODE=6555 BINDIR= /usr/bin include ../Makefile.in lpr-2008.05.17.3+nmu1/lpr/lpr.10000644000000000000000000001611711013660167012301 0ustar .\" $OpenBSD: lpr.1,v 1.11 2007/05/31 19:20:25 jmc Exp $ .\" $NetBSD: lpr.1,v 1.10 2002/01/19 03:23:26 wiz Exp $ .\" .\" 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. 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 $Mdocdate: May 31 2007 $ .Dt LPR 1 .Os .Sh NAME .Nm lpr .Nd off line print .Sh SYNOPSIS .Nm lpr .Bk -words .Op Fl cdfghlmnpqrstv .Op Fl # Ns Ar num .Op Fl 1234 Ar font .Op Fl C Ar class .Op Fl i Op Ar numcols .Op Fl J Ar job .Op Fl P Ns Ar printer .Op Fl T Ar title .Op Fl U Ar user .Op Fl w Ns Ar num .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 .Ic cifplot . .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 .Ic 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. .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 h Suppress the printing of the burst page. .It Fl m Send mail upon completion. .It Fl P Ns Ar printer 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 q Queue the print job but do not start the spooling daemon. .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 .Pp 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 Fl 1234 Ar font 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 i Op Ar 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 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 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 local users database .It Pa /etc/printcap printer capabilities database .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 .Dq cf files .It Pa /var/spool/output/*/tf* temporary copies of .Dq cf files .El .Sh DIAGNOSTICS If you try to spool too large a file, it will be truncated. If a user other than root prints a file and spooling is disabled, .Nm will print a message saying so and will not put jobs in the queue. If a connection to .Xr lpd 8 on the local machine cannot be made, .Nm 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 8 . .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 command appeared in .Bx 3 . .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. lpr-2008.05.17.3+nmu1/lpr/lpr.c0000644000000000000000000004054013416163523012363 0ustar /* $OpenBSD: lpr.c,v 1.41 2007/04/07 21:57:27 stevesk Exp $ */ /* $NetBSD: lpr.c,v 1.19 2000/10/11 20:23:52 is Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static const char sccsid[] = "@(#)lpr.c 8.4 (Berkeley) 4/28/95"; #else static const char rcsid[] = "$OpenBSD: lpr.c,v 1.41 2007/04/07 21:57:27 stevesk Exp $"; #endif #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 #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 const 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 char *width; /* width for versatec printing */ static struct stat statb; volatile sig_atomic_t gotintr; static void card(int, const char *); static void chkprinter(char *); static void cleanup(int); static void copy(int, char *); static char *itoa(int); static char *linked(char *); static char *lmktemp(char *, int); static void mktemps(void); static int nfile(char *); static int test(char *); static void usage(void); int main(int argc, char **argv) { struct passwd *pw; struct group *gptr; char *arg, *cp; char buf[MAXPATHLEN]; int i, f, ch; struct stat stb; /* * Simulate setuid daemon w/ PRIV_END called. * We don't want lpr to actually be setuid daemon since that * requires that the lpr binary be owned by user daemon, which * is potentially unsafe. */ if ((pw = getpwnam(DEFUID)) == NULL) errx(1, "'lp' uid not in password file"); effective_uid = pw->pw_uid; real_uid = getuid(); effective_gid = pw->pw_gid; real_gid = getgid(); setresgid(real_gid, real_gid, effective_gid); setresuid(real_uid, real_uid, effective_uid); 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); gethostname(host, sizeof (host)); openlog("lpr", 0, LOG_LPR); while ((ch = getopt(argc, argv, ":#:1:2:3:4:C:J:P:T:U:cdfghi::lmnpqrstvw:")) != -1) { switch (ch) { case '#': /* n copies */ if (isdigit(*optarg)) { i = atoi(optarg); if (i > 0) ncopies = i; } case '4': /* troff fonts */ case '3': case '2': case '1': fonts[ch - '1'] = optarg; break; case 'C': /* classification spec */ hdr++; class = optarg; break; case 'J': /* job name */ hdr++; jobname = optarg; break; case 'P': /* specifiy printer name */ printer = optarg; break; case 'T': /* pr's title line */ title = optarg; break; case 'U': /* user name */ hdr++; person = optarg; break; case 'c': /* print cifplot output */ case 'd': /* print tex output (dvi files) */ case 'g': /* print graph(1G) output */ case 'l': /* literal output */ case 'n': /* print ditroff output */ case 'p': /* print using ``pr'' */ case 't': /* print troff output (cat files) */ case 'v': /* print vplot output */ format = ch; break; case 'f': /* print fortran output */ format = 'r'; break; case 'h': /* toggle want of header page */ hdr = !hdr; break; case 'i': /* indent output */ iflag++; if ( optarg == 0 || (indent = atoi(optarg)) < 0) indent = 8; break; case 'm': /* send mail when done */ mailflg++; break; case 'q': /* just q job */ qflag++; break; case 'r': /* remove file when done */ rflag++; break; case 's': /* try to link files */ sflag++; break; case 'w': /* versatec page width */ width = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (printer == NULL && (printer = getenv("PRINTER")) == NULL) printer = DEFLP; chkprinter(printer); if (SC && ncopies > 1) errx(1, "multiple copies are not allowed"); if (MC > 0 && ncopies > MC) errx(1, "only %ld copies are allowed", MC); /* * Get the identity of the person doing the lpr using the same * algorithm as lprm. */ if (real_uid != DU || person == NULL) { if ((pw = getpwuid(real_uid)) == NULL) errx(1, "Who are you?"); if ((person = strdup(pw->pw_name)) == NULL) err(1, NULL); } /* * Check for restricted group access. */ if (RG != NULL && real_uid != DU) { if ((gptr = getgrnam(RG)) == NULL) errx(1, "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) errx(1, "Not a member of the restricted group"); } } /* * Check to make sure queuing is enabled if real_uid is not root. */ (void)snprintf(buf, sizeof(buf), "%s/%s", SD, LO); if (real_uid && stat(buf, &stb) == 0 && (stb.st_mode & 010)) errx(1, "Printer queue is disabled"); /* * Initialize the control file. */ mktemps(); tfd = nfile(tfname); card('H', host); card('P', person); if (hdr) { if (jobname == NULL) { if (argc == 0) jobname = "stdin"; else jobname = (arg = strrchr(argv[0], '/')) ? arg + 1 : argv[0]; } card('J', jobname); card('C', class); if (!SH) 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 == 0) copy(0, " "); else while (argc--) { if (argv[0][0] == '-' && argv[0][1] == '\0') { /* use stdin */ copy(0, " "); argv++; continue; } if ((f = test(arg = *argv++)) < 0) continue; /* file unreasonable */ if (sflag && (cp = linked(arg)) != NULL) { (void)snprintf(buf, sizeof(buf), "%llu %d", (unsigned long long int)makedev( major(statb.st_dev), minor(statb.st_dev)), (int)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) warnx("%s: not linked, copying instead", arg); if ((i = safe_open(arg, O_RDONLY, 0)) < 0) warn("%s", arg); else { copy(i, arg); (void)close(i); if (f && unlink(arg) < 0) warnx("%s: not removed", arg); } } if (nact) { (void)close(tfd); tfname[inchar]--; /* * Touch the control file to fix position in the queue. */ PRIV_START; if ((tfd = safe_open(tfname, O_RDWR|O_NOFOLLOW, 0)) >= 0) { char c; if (read(tfd, &c, 1) == 1 && lseek(tfd, (off_t)0, SEEK_SET) == 0 && write(tfd, &c, 1) != 1) { warn("%s", tfname); tfname[inchar]++; cleanup(0); } (void)close(tfd); } if (link(tfname, cfname) < 0) { warn("cannot rename %s", cfname); tfname[inchar]++; cleanup(0); } unlink(tfname); PRIV_END; if (qflag) /* just q things up */ exit(0); if (!startdaemon(printer)) printf("jobs queued, but cannot start daemon.\n"); exit(0); } cleanup(0); return (1); /* NOTREACHED */ } /* * Create the file n and copy from file descriptor f. */ static void copy(int f, char *n) { 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, sizeof(buf))) > 0) { if (write(fd, buf, i) != i) { warn("%s", n); break; } nc += i; if (nc >= sizeof(buf)) { nc -= sizeof(buf); nr++; if (MX > 0 && nr > MX) { warnx("%s: copy file is too large", n); break; } } } (void)close(fd); if (nc == 0 && nr == 0) warnx("%s: empty input file", 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(char *file) { char *cp; static char buf[MAXPATHLEN]; int ret; if (*file != '/') { if (getcwd(buf, sizeof(buf)) == NULL) return(NULL); while (file[0] == '.') { switch (file[1]) { case '/': file += 2; continue; case '.': if (file[2] == '/') { if ((cp = strrchr(buf, '/')) != NULL) *cp = '\0'; file += 3; continue; } } break; } if (strlcat(buf, "/", sizeof(buf)) >= sizeof(buf) || strlcat(buf, file, sizeof(buf)) >= sizeof(buf)) return(NULL); file = buf; } PRIV_START; ret = symlink(file, dfname); PRIV_END; return(ret ? NULL : file); } /* * Put a line into the control file. */ static void card(int c, const char *p2) { char buf[BUFSIZ]; char *p1 = buf; int len = 2; if (strlen(p2) > sizeof(buf) - 2) errx(1, "Internal error: String longer than %ld", (long)sizeof(buf)); *p1++ = c; while ((c = *p2++) != '\0' && len < sizeof(buf)) { *p1++ = (c == '\n') ? ' ' : c; len++; } *p1++ = '\n'; write(tfd, buf, len); } /* * Create a new file in the spool directory. */ static int nfile(char *n) { int f; int oldumask = umask(0); /* should block signals */ PRIV_START; f = open(n, O_WRONLY|O_EXCL|O_CREAT, FILMOD); (void)umask(oldumask); if (f < 0) { warn("%s", n); cleanup(0); } PRIV_END; if (++n[inchar] > 'z') { if (++n[inchar-2] == 't') { warnx("too many files - break up the job"); cleanup(0); } n[inchar] = 'A'; } else if (n[inchar] == '[') n[inchar] = 'a'; return (f); } /* * Cleanup after interrupts and errors. */ static void cleanup(int signo) { int i; signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGTERM, SIG_IGN); i = inchar; PRIV_START; 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(char *file) { int fd; char *cp; if ((fd = open(file, O_RDONLY|O_NONBLOCK)) < 0) { warn("cannot open %s", file); goto bad; } if (fstat(fd, &statb) < 0) { warn("cannot stat %s", file); goto bad; } if (S_ISDIR(statb.st_mode)) { warnx("%s is a directory", file); goto bad; } if (!S_ISREG(statb.st_mode)) { warnx("%s is not a regular file", file); goto bad; } if (statb.st_size == 0) { warnx("%s is an empty file", file); goto bad; } (void)close(fd); if (rflag) { if ((cp = strrchr(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); } warnx("%s is not removable by you", file); } return(0); bad: return(-1); } /* * itoa - integer to string conversion */ static char * itoa(int i) { static char b[10] = "########"; 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(char *s) { int status; if ((status = cgetent(&bp, printcapdb, s)) == -2) errx(1, "cannot open printer description file"); else if (status == -1) errx(1, "%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 = DEFNUID; SC = (cgetcap(bp, "sc", ':') != NULL); SH = (cgetcap(bp, "sh", ':') != NULL); } /* * Make the temp files. */ static void mktemps(void) { int len, fd, n; char *cp; char buf[BUFSIZ]; struct stat stb; if (snprintf(buf, sizeof(buf), "%s/.seq", SD) >= sizeof(buf)) errx(1, "%s/.seq: %s", SD, strerror(ENAMETOOLONG)); PRIV_START; if ((fd = safe_open(buf, O_RDWR|O_CREAT|O_NOFOLLOW, 0661)) < 0) err(1, "cannot open %s", buf); if (flock(fd, LOCK_EX)) err(1, "cannot lock %s", buf); PRIV_END; 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'); } } do { tfname = lmktemp("tf", n); cfname = lmktemp("cf", n); dfname = lmktemp("df", n); n = (n + 1) % 1000; } while (stat(tfname, &stb) == 0 || stat(cfname, &stb) == 0 || stat(dfname, &stb) == 0); inchar = strlen(SD) + 3; (void)lseek(fd, (off_t)0, SEEK_SET); snprintf(buf, sizeof(buf), "%03d\n", n); (void)write(fd, buf, strlen(buf)); (void)close(fd); /* unlocks as well */ } /* * Make a temp file name. */ static char * lmktemp(char *id, int num) { char *s; if (asprintf(&s, "%s/%sA%03d%s", SD, id, num, host) == -1) err(1, NULL); return(s); } static void usage(void) { extern char *__progname; fprintf(stderr, "usage: %s [-cdfghlmnpqrstv] [-#num] [-1234 font] " "[-C class] [-i [numcols]]\n" "\t[-J job] [-Pprinter] [-T title] [-U user] " "[-wnum] [name ...]\n", __progname); exit(1); } lpr-2008.05.17.3+nmu1/lprm/0000755000000000000000000000000013416173536011601 5ustar lpr-2008.05.17.3+nmu1/lprm/Makefile0000644000000000000000000000060110176611664013235 0ustar # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $OpenBSD: Makefile,v 1.6 2003/03/11 04:36:55 millert Exp $ PROG= lprm CFLAGS+=-I${.CURDIR}/../common_source SRCS= lprm.c ../common_source/rmjob.c ../common_source/startdaemon.c ../common_source/common.c \ ../common_source/common_vars.c ../common_source/getcap.c BINOWN= root BINGRP= daemon BINMODE=6555 BINDIR= /usr/bin include ../Makefile.in lpr-2008.05.17.3+nmu1/lprm/lprm.10000644000000000000000000001062011013660223012615 0ustar .\" $OpenBSD: lprm.1,v 1.10 2007/05/31 19:20:25 jmc Exp $ .\" $NetBSD: lprm.1,v 1.10 2002/01/19 03:23:47 wiz Exp $ .\" .\" 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. 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 $Mdocdate: May 31 2007 $ .Dt LPRM 1 .Os .Sh NAME .Nm lprm .Nd remove jobs from the line printer spooling queue .Sh SYNOPSIS .Nm lprm .Op Fl .Op Fl P Ns Ar printer .Oo .Op Ar job# Ar ... .Op Ar user Ar ... .Oc .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 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 .Dq Fl is given, .Nm will remove all jobs which a user owns. If the superuser employs this flag, the spool queue will be emptied entirely. .It Ar user Causes .Nm to attempt to remove any jobs queued belonging to that user (or users). This form of invoking .Nm is useful only to the superuser. .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 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 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/output/*/lock/ -compact .It Pa /etc/printcap Printer characteristics file. .It Pa /var/spool/output/* Spooling directories. .It Pa /var/spool/output/*/lock Lock file used to obtain the PID of the current daemon and the job number of the currently active job. .El .Sh DIAGNOSTICS .Bl -tag -width Ds .It Sy Permission denied Printed if the user tries to remove files other than his own. .El .Sh SEE ALSO .Xr lpq 1 , .Xr lpr 1 , .Xr lpd 8 .Sh HISTORY The .Nm lprm command appeared in .Bx 3.0 . .Sh BUGS Since there are race conditions possible in the update of the lock file, the currently active job may be incorrectly identified. lpr-2008.05.17.3+nmu1/lprm/lprm.c0000644000000000000000000001213611013660223012703 0ustar /* $OpenBSD: lprm.c,v 1.17 2007/02/16 13:34:58 jmc Exp $ */ /* $$NetBSD: lprm.c,v 1.9 1999/08/16 03:12:32 simonb Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static const char sccsid[] = "@(#)lprm.c 8.1 (Berkeley) 6/6/93"; #else static const char rcsid[] = "$OpenBSD: lprm.c,v 1.17 2007/02/16 13:34:58 jmc Exp $"; #endif #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. Privileged users may remove anyone's spool * entries, otherwise one can only remove their own. */ #include #include #include #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 */ volatile sig_atomic_t gotintr; /* set when we receive SIGINT */ static char luser[LOGIN_NAME_MAX /*MAXLOGNAME*/]; /* buffer for person */ static void usage(void); int main(int argc, char **argv) { struct passwd *pw; char *cp; long l; int ch; /* * Simulate setuid daemon w/ PRIV_END called. * We don't want lpr to actually be setuid daemon since that * requires that the lpr binary be owned by user daemon, which * is potentially unsafe. */ if ((pw = getpwnam(DEFUID)) == NULL) errx(1, "'lp' uid not in password file"); effective_uid = pw->pw_uid; real_uid = getuid(); effective_gid = pw->pw_gid; real_gid = getgid(); setresgid(real_gid, real_gid, effective_gid); setresuid(real_uid, real_uid, effective_uid); gethostname(host, sizeof(host)); openlog("lprm", 0, LOG_LPR); if ((pw = getpwuid(real_uid)) == NULL) fatal("Who are you?"); if (strlen(pw->pw_name) >= sizeof(luser)) fatal("Your name is too long"); strlcpy(luser, pw->pw_name, sizeof(luser)); person = luser; while ((ch = getopt(argc, argv, "P:w")) != -1) { switch (ch) { case 'P': printer = optarg; break; case 'w': l = strtol(optarg, &cp, 10); if (*cp != '\0' || l < 0 || l >= INT_MAX) errx(1, "wait time must be postive integer: %s", optarg); wait_time = (u_int)l; if (wait_time < 30) warnx("warning: wait time less than 30 seconds"); break; default: usage(); } } argc -= optind; argv += optind; if (printer == NULL && (printer = getenv("PRINTER")) == NULL) printer = DEFLP; /* getopt doesn't handle '-' as an argument so we have to handle it here manually */ if(argc == 1 && *argv[0] == '-' && strlen(argv[0]) == 1) { argc--; argv++; users = -1; } if (users < 0 && argc != 0) usage(); while (argc > 0) { if (isdigit(*argv[0])) { if (requests >= MAXREQUESTS) fatal("Too many requests"); requ[requests++] = atoi(argv[0]); } else { if (users >= MAXUSERS) fatal("Too many users"); user[users++] = argv[0]; } argc--; argv++; } rmjob(); exit(0); } static void usage(void) { extern char *__progname; fprintf(stderr, "usage: %s [-] [-Pprinter] [[job# ...] [user ...]]\n", __progname); exit(2); } lpr-2008.05.17.3+nmu1/lptest/0000755000000000000000000000000013416173536012142 5ustar lpr-2008.05.17.3+nmu1/lptest/Makefile0000644000000000000000000000025610176611664013604 0ustar # from: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $OpenBSD: Makefile,v 1.2 1997/01/17 16:12:48 millert Exp $ PROG= lptest BINDIR= /usr/bin SRCS= lptest.c include ../Makefile.in lpr-2008.05.17.3+nmu1/lptest/lptest.10000644000000000000000000000517711013660255013537 0ustar .\" $OpenBSD: lptest.1,v 1.7 2007/05/31 19:20:25 jmc Exp $ .\" $NetBSD: lptest.1,v 1.7 1999/03/22 18:44:00 garbled Exp $ .\" .\" 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. 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 $Mdocdate: May 31 2007 $ .Dt LPTEST 1 .Os .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 .Dq 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 also be specified. .Sh HISTORY .Nm appeared in .Bx 4.3 . lpr-2008.05.17.3+nmu1/lptest/lptest.c0000644000000000000000000000517007666757625013645 0ustar /* $OpenBSD: lptest.c,v 1.7 2003/06/02 23:36:53 millert Exp $ */ /* $NetBSD: lptest.c,v 1.6 1996/12/09 09:57:50 mrg Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static const char sccsid[] = "@(#)lptest.c 8.1 (Berkeley) 6/6/93"; #else static const char rcsid[] = "$OpenBSD: lptest.c,v 1.7 2003/06/02 23:36:53 millert Exp $"; #endif #endif /* not lint */ #include #include /* * lptest -- line printer test program (and other devices). */ int main(int argc, char **argv) { int len, count; int 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); } lpr-2008.05.17.3+nmu1/pac/0000755000000000000000000000000013416173536011372 5ustar lpr-2008.05.17.3+nmu1/pac/Makefile0000644000000000000000000000045510176611664013035 0ustar # from: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $OpenBSD: Makefile,v 1.3 2002/05/20 23:13:50 millert Exp $ PROG= pac CFLAGS+=-I${.CURDIR}/../common_source MAN= pac.8 SRCS= pac.c ../common_source/common.c ../common_source/common_vars.c ../common_source/getcap.c BINDIR=/usr/sbin include ../Makefile.in lpr-2008.05.17.3+nmu1/pac/pac.80000644000000000000000000001004011013660567012215 0ustar .\" $OpenBSD: pac.8,v 1.9 2007/05/31 19:20:25 jmc Exp $ .\" $NetBSD: pac.8,v 1.9 2002/01/19 03:24:14 wiz Exp $ .\" .\" 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. 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 $Mdocdate: May 31 2007 $ .Dt PAC 8 .Os .Sh NAME .Nm pac .Nd printer/plotter accounting information .Sh SYNOPSIS .Nm pac .Op Fl cmrs .Bk -words .Op Fl P Ns Ar printer .Ek .Bk -words .Op Fl p Ns Ar price .Ek .Op Ar user ... .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 named .Ar user , and prints out how much each user consumed in pages or feet and dollars. .Pp When no .Ar user arguments are given, statistics are printed for every user who has used any paper. .Pp The options are as follows: .Bl -tag -width Ds .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 Causes the output to be sorted by cost; usually the output is sorted alphabetically by name. .It Fl m 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. .El .Sh OUTPUT FORMAT .Nm formats the output into a simple table, using four columns: .Bl -enum .It The host name followed by the user's login name (column "Login"). If the .Fl m option was specified, the host name will be omitted. .It The number of pages or feet printed (column "pages/feet"). .It The number of copies made (column "runs"). .It The total price for the user (column "price"). .El .Pp If no .Ar user argument was specified, .Nm will print a summary line with print totals. .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 database .El .Sh SEE ALSO .Xr printcap 5 .Sh HISTORY The .Nm command appeared in .Bx 4.0 . .Sh BUGS The relationship between the computed price and reality is as yet unknown. lpr-2008.05.17.3+nmu1/pac/pac.c0000644000000000000000000002514611013660271012275 0ustar /* $OpenBSD: pac.c,v 1.18 2007/09/02 15:19:39 deraadt Exp $ */ /* $NetBSD: pac.c,v 1.14 2000/04/27 13:40:18 msaitoh Exp $ */ /* * 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. 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 const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static const char sccsid[] = "@(#)pac.c 8.1 (Berkeley) 6/6/93"; #else static const char rcsid[] = "$OpenBSD: pac.c,v 1.18 2007/09/02 15:19:39 deraadt Exp $"; #endif #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 #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 */ volatile sig_atomic_t gotintr; /* * 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(FILE *); static int chkprinter(const char *); static void dumpit(void); static int hash(const char *); static struct hent *enter(const char *); static struct hent *lookup(const char *); static int qucmp(const void *, const void *); static void rewrite(void); void usage(void); int main(int argc, char **argv) { FILE *acct; int ch; /* these aren't actually used in pac(1) */ effective_uid = geteuid(); real_uid = getuid(); effective_gid = getegid(); real_gid = getgid(); while ((ch = getopt(argc, argv, "P:p:scmr")) != -1) { switch (ch) { case 'P': /* * Printer name. */ printer = optarg; continue; case 'p': /* * get the price. */ price = atof(optarg); 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: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; /* * If there are any arguments left, they're names of users * we want to print info for. In that case, put them in the hash * table and unset allflag. */ for( ; argc > 0; argc--, argv++) { (void)enter(*argv); allflag = 0; } if (printer == NULL && (printer = getenv("PRINTER")) == NULL) printer = DEFLP; if (!chkprinter(printer)) errx(2, "unknown printer: %s", printer); if ((acct = fopen(acctfile, "r")) == NULL) err(1, "%s", acctfile); 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 accommodate both the active and summary file * formats here. * The Format of the accounting file is: * feet_per_page [runs_count] [hostname:]username * Some software relies on whitespace between runs_count and hostname:username * being optional (such as Ghostscript's unix-lpr.sh). * * Host names are ignored if the -m flag is present. */ static void account(FILE *acct) { char linebuf[BUFSIZ]; double t; long l; char *cp, *cp2, *ep; struct hent *hp; int ic; while (fgets(linebuf, sizeof(linebuf), acct) != NULL) { cp = linebuf; while (isspace(*cp)) cp++; /* get t, feet_per_page */ errno = 0; t = strtod(cp, &ep); if (!isspace(*ep) || errno == ERANGE) continue; /* get ic, runs_count (optional) */ for (cp = ep + 1; isspace(*cp); ) cp++; l = strtol(cp, &ep, 10); if (cp == ep) l = 0; /* runs_count not specified */ else if (l < 0 || l >= INT_MAX) continue; ic = (int)l; /* get [hostname:]username */ for (cp = ep; isspace(*cp); cp++) ; for (cp2 = cp; *cp2 && !isspace(*cp2); cp2++) ; *cp2 = '\0'; /* if -m was specified, don't use the hostname part */ if (mflag && (cp2 = strchr(cp, ':')) != NULL) cp = cp2 + 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(void) { struct hent **base; struct hent *hp, **ap; int hno, c, runs; float feet; hp = hashtab[0]; hno = 1; base = (struct hent **) calloc(hcount, sizeof(hp)); if (base == NULL) err(1, NULL); 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(void) { struct hent *hp; int i; FILE *acctf; if ((acctf = fopen(sumfile, "w")) == NULL) { warn("%s", 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)) { warn("%s", sumfile); errs++; } fclose(acctf); if ((acctf = fopen(acctfile, "w")) == NULL) warn("%s", acctfile); else fclose(acctf); } /* * Hashing routines. */ /* * Enter the name into the hash table and return the pointer allocated. */ static struct hent * enter(const char *name) { struct hent *hp; int h; if ((hp = lookup(name)) != NULL) return(hp); h = hash(name); hcount++; hp = (struct hent *) malloc(sizeof *hp); if (hp == NULL) err(1, NULL); hp->h_name = strdup(name); if (hp->h_name == NULL) err(1, NULL); 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(const char *name) { int h; 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(const char *name) { int h; const char *cp; for (cp = name, h = 0; *cp; h = (h << 2) + *cp++) ; return((h & 0x7fffffff) % HSHSIZE); } /* * The qsort comparison routine. * The comparison is ascii collating order * or by feet of typesetter film, according to sort. */ static int qucmp(const void *a, const void *b) { struct hent *h1, *h2; 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(const char *s) { int stat; int len; 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; len = strlen(acctfile) + 5; sumfile = (char *) malloc(len); if (sumfile == NULL) err(1, "pac"); strlcpy(sumfile, acctfile, len); strlcat(sumfile, "_sum", len); return(1); } void usage(void) { extern char *__progname; fprintf(stderr, "usage: %s [-cmrs] [-Pprinter] [-pprice] [user ...]\n", __progname); exit(1); }