home *** CD-ROM | disk | FTP | other *** search
- Subject: v16i020: Public lineprinter spooler package, Part07/16
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: papowell@julius.cs.umn.edu
- Posting-number: Volume 16, Issue 20
- Archive-name: plp/part07
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 7 (of 16)."
- # Contents: doc/PLP/06.t doc/PLP/07.t src/checkpc.c
- # src/remoteprinter.c src/startprinter.c
- # Wrapped by papowell@attila on Wed Aug 10 10:44:57 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'doc/PLP/06.t' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'doc/PLP/06.t'\"
- else
- echo shar: Extracting \"'doc/PLP/06.t'\" \(10628 characters\)
- sed "s/^X//" >'doc/PLP/06.t' <<'END_OF_FILE'
- X.ig
- X$Header: 06.t,v 1.1 88/05/21 18:39:41 papowell Locked $
- X$log$
- X..
- X.NH 1
- Local Spool Queues and Servers
- X.PP
- The
- X.I lpd
- process
- handles the unspooling process for local and remote spool queues in
- much the same manner.
- X.I Lpd
- forks a server process to unspool entries from a queue.
- The server (or unspooler) process checks the spool queue lock file to see if
- unspooling is enabled,
- sorts jobs according to priority,
- and then takes printing actions as specified by the
- printcap entry for the spool queue.
- In order to provide fine control over the printing process,
- the unspooler forks a set of filter processes
- based on information in the printcap entry to handle specialized printer
- requirements.
- These filter processes are used to:
- X.IP 1). 3
- Provide control over device dependencies,
- above that allowed by the simple serial line control functions.
- X.IP 2). 3
- Print banners or job separator information.
- X.IP 3). 3
- Provide specific processing for a particular job format.
- X.IP 4). 3
- Provide accounting information.
- X.PP
- Different classes of output devices require different amounts or kinds of
- filter support.
- The following sections outline the different options
- and the filter support provided for them.
- X.NH 2
- Job Format and Filter Selection
- X.PP
- Associated with each data file of a job is a unspooling format.
- When unspooling a job,
- the server uses this format to select a filter to be used to process
- the data file.
- By convention,
- the format used for printing a job is specified by
- a lower case letter (a\-z),
- and the corresponding filter for the format is specified by
- the printcap field
- x\c
- X.B f,
- where x represents the format.
- This is not uniformly true,
- as the
- X.B af
- X(accounting file name),
- X.B lf
- X(log file name),
- and
- X.B ff
- X(form feed string)
- entries are used for other purposes.
- In Figure 6.1,
- X.B af
- specifies the accounting file,
- X.B lf
- is the log file,
- and
- X.B of ,
- X.B if ,
- and
- X.B tf
- are filter programs.
- X.KF
- X.DT
- X.nf
- X.SM
- X.L
- X.in +1i
- X# Versatec Printer, Lind 33
- X# Uses the new filters
- versatec_lind33\||\|versatec:\e
- X :fx=flpdt:mx#2000:\e
- X :lp=/dev/va0:sd=/usr/spool/versatec_lind33:\e
- X :af=vaacct:\e
- X :lf=logfile:\e
- X :of=/usr/lib/vpf:\e
- X :if=/usr/lib/vpf:\e
- X :df=/usr/lib/vpf:\e
- X :tf=/usr/lib/rvcat:
- X.in -1i
- X.LG
- X.R
- X.ce
- XFigure 6.1. Local Printer Printcap Entry
- X.KE
- X.NH 2
- No Filter Support Specified
- X.PP
- If no output filters are specified,
- the server opens the output device,
- sets the serial line characteristics if it is a serial line,
- and prints directly to the output device.
- X.NH 2
- Banners and Separators
- X.PP
- By default,
- jobs are separated by a banner page or separator page that is generated by the
- server process.
- The default banner is a single page,
- with the user name and job information printed in large letters.
- The
- X.B sb
- X(short banner)
- option specifies a single line banner of the following form:
- X.nf
- X.ti +5
- X.L "[user]:[host] Job: [jobname] Date: [date]"
- X.ti +5
- X.L "papowell:attila.cs.umn.edu Job: (stdin) Date: Fri May 20 11:29:05 1988"
- X.fi
- X.PP
- The
- X.B sh
- X(suppress header)
- flag suppress banner printing.
- The
- X.I lpr
- no header option
- X(\-h)
- allows the user to request no header or banner for the job;
- the
- X.B ab
- X(always print banner) printcap flag
- causes the server to ignore the no banner request.
- X.PP
- Consecutive printer jobs are normally separated by a form feed;
- the default (c
- X.B \ef )
- can be changed by specifying a value for the
- X.B ff
- X(form feed string) field.
- The
- X.B sf
- X(suppress form feeds)
- can be used to suppress any printing of form feeds between jobs.
- When the printer is started,
- it may be necessary to initialize the printer by sending some additional
- information.
- The
- X.B fo
- X(form feed on open) flag specifies that the
- X.B ff
- string is printed before the first job,
- and the
- X.B fq
- X(form feed on quitting)
- flag specifies that a form feed is printed after the last job.
- In addition,
- X.B ld
- X(leader on open) specifies a string to be printed before the
- X(optional) intial form feed
- and the
- X.B tr
- X(trailer) specifies a string to be printed after the
- the (optional) final form feed.
- The
- X.B ld
- and
- X.B tr
- strings are useful for specifying an escape sequence that sets up
- form length, etc.
- X.PP
- In addition to the built in banner printer,
- the
- X.B bp
- X(banner printer)
- and
- X.B ep
- X(end printer)
- fields can be used to specify banner and trailer printing programs.
- These programs are invoked to print banners or other information after the
- built in banner or separator has been printed.
- Custom banner printing may be done by suppressing built in banners with
- X.B sh
- and
- X.B sf
- and using the
- X.B bp
- and
- X.B ep
- entries.
- X.NH 2
- Simple OF and IF Filter Support
- X.PP
- The
- X.B OF
- X(output filter)
- specified by the
- X.B of
- field is used by the server to
- print banners and provide a simple filter action for devices that
- need a minmum amount of control.
- The OF filter
- is not intended to perform accounting since it is started only once
- and no provision is made for passing
- owners' login name,
- identifying the begining and ending of jobs,
- etc.
- X.PP
- The OF filter is started when the server discovers that it has a
- job to print.
- The server will open the output device,
- do any line control operations,
- and then start the OF filter.
- Banner and job separator strings will be sent to the
- OF filter,
- which filters them and sends them to the output device.
- In order to use other filters,
- the server will request the OF
- filter to suspend itself by sending it the two character sequence
- X\e031\e001 or ESC ^A.
- The OF filter should then suspend itself by using a
- X.L "kill(0,SIGSTOP)" .
- The server will wait for this event,
- and then start up other filters.
- After they have completed,
- the server will signal the OF filter to continue by using
- X.L "kill(OF_pid,SIGCONT)" .
- X.PP
- The IF filter
- specified by the
- X.B if
- field is used to format jobs with the
- X.B f
- format,
- which is for ordinary textual output.
- The
- X.I lpr
- program will use
- X.B f
- format by default if no format is specified,
- and also for printing literal output
- X(lpr \-l option)
- or
- X.I pr
- output (lpr \-p option).
- The IF filter is expected to do formatting and update an accounting file.
- If there is no IF filter and an
- X.B f
- format job is printed,
- it is filtered through the
- X.B OF
- filter.
- If there is no OF filter,
- then the printer will copy the file directly to the output device.
- X.NH 2
- Non-standarstandard Formats and Filters
- X.PP
- The
- X.B lpr
- program allows the user to specify a job format;
- the
- X.B f
- format is the default format for text files.
- The
- X.B fx
- printcap field specifies the formats allowed on the printer;
- the default permitted formats are
- X.L "f, l,"
- and
- X.L "p" .
- The
- X.B lpr
- program checks to see if the requested format is allowed when
- it spools a job.
- XEach format must have a corresponding filter,
- which is used to process data files of the specified format.
- Note that these filters may be invoked once per data file,
- or the entire set of data files may be combined into a single file
- and passed through a single invocation of the filter.
- Usually the effects of doing this are indistinguishable,
- but some filters will cause an alignment of printer media
- to be done for each invocation.
- This is an implementation dependent phenomina.
- X.PP
- The commonly available set of formats is specified in the
- X.I lpr
- man page.
- The
- X.I "f"
- X(default),
- X.I "l"
- X(literal),
- and
- X.I p
- X(use the ``pr'' program to format output)
- formats are printed using the
- X.B if
- output filter.
- The
- X.I lpr
- X\-f option is used to specify printing with a filter that
- handles FORTRAN formats;
- this flag is translated by
- X.I lpr
- into printing with the
- X.B r
- format.
- The
- X.I "a, i, l,"
- and
- X.I "o"
- formats are unavailable,
- as their filter names
- X(\c
- X.L af,
- X.L if,
- X.L lf
- and
- X.L of )
- are used for other purposes.
- X.NH 2
- Prefilters
- X.PP
- The
- X.I lpr
- program can pre-filter files before spooling them.
- The
- X.B Xe
- field is used to specify that format
- X.B X
- files are to processed by the specified prefilter.
- The prefilter specification consists of the pathname and arguments of the
- prefilter program,
- followed by the format that is to be used for spooling the output.
- X.KF
- X.DT
- X.L
- X.SM
- X.nf
- X.in +1i
- X# Versatec Printer, Lind 33
- X# Uses a prefilter for f format
- versatec_lind33\||\|versatec:\e
- X :fx=flpdt:mx#2000:\e
- X :lp=/dev/va0:sd=/usr/spool/versatec_lind33:\e
- X :af=/usr/adm/vaacct:\e
- X :of=/usr/lib/vpf:\e
- X :if=/usr/lib/vpf:\e
- X :df=/usr/lib/vpf:\e
- X :tf=/usr/lib/rvcat:\e
- X :fe=/usr/local/lib/vprintup -X w4,f:
- X.R
- X.LG
- X.in -1i
- X.ce
- XFigure 6.2 Prefilter Printcap Entry
- X.KE
- XFor example,
- the printcap entry in Figure 6.2 specifies that
- X.B f
- format files are prefiltered through
- X.I vprintup
- and the output is in the
- X.I f
- format.
- X.NH 2
- Special Queue Handlers
- X.PP
- If the user does not like the way that the PLP server handles files,
- the printcap can be used to specify a queue handler program
- to handle processing of the job and data files.
- This is useful when you are sending files to a remote machine
- using a special protocol or a remote procedure call.
- The printcap queue handler field
- X.B qh
- specifies a program which will be responsible
- for handling the job.
- X.KF
- X.DT
- X.L
- X.SM
- X.nf
- X.in +1i
- X.ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n 8i
- X# Special queue entry, used for bizzare purposes
- X# The queue_handler program will take care of everything
- special:\e
- X :lp=/dev/null:\e
- X :qh=/usr/local/lib/queue_handler:
- X.R
- X.LG
- X.in -1i
- X.ce
- XFigure 6.3 Queue Handler Printcap Entry
- X.KE
- X.PP
- The queue handler is invoked once per queue entry,
- and exits with a 0 (successful),
- X1 (unsuccessful, retry),
- or other (give up and delete entry) status.
- XError messages printed on
- X.I stderr
- X(file descriptor 2) will be placed in the spool queue log file.
- X.NH 2
- Multiple Servers For a Spool Queue
- X.PP
- If a spool queue has multiple servers,
- they are specified using the
- X.B sv
- X(servers) parameter,
- which contains a comma separated list of server entries in the printcap file.
- The printcap entry for a server contains a
- X.B ss
- X(serves) parameter which contains the name of the spool queue that it
- serves.
- X.PP
- Printcap entries for the server are determined in the following manner.
- When the spool queue server starts up,
- it reads the spool queue printcap entry,
- and determines that there are multiple servers for the queue.
- It then forks a printer server process for each name in the
- X.B sv
- list.
- X.PP
- The individual printer server process reads the printcap entry for the
- individual printer,
- overwriting or adding any existing values read from printcap for the
- spool queue.
- Since server entries use the
- the spool directory of the spool queue,
- their individual log and other files should have
- distinct names.
- Common information can be put in the spool queue printcap entry,
- and entries that differ for each printer,
- such as the output device,
- need to appear the individual printer printcap entry.
- END_OF_FILE
- if test 10628 -ne `wc -c <'doc/PLP/06.t'`; then
- echo shar: \"'doc/PLP/06.t'\" unpacked with wrong size!
- fi
- # end of 'doc/PLP/06.t'
- fi
- if test -f 'doc/PLP/07.t' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'doc/PLP/07.t'\"
- else
- echo shar: Extracting \"'doc/PLP/07.t'\" \(9734 characters\)
- sed "s/^X//" >'doc/PLP/07.t' <<'END_OF_FILE'
- X.ig
- X$Header: 07.t,v 1.1 88/05/21 18:39:43 papowell Locked $
- X$log$
- X..
- X.bp
- X.NH 1
- XFilter Support
- X.PP
- The filter programs are started by a queue server
- in order to support specialized unspooling operations.
- While the server process runs SUID
- X.L root ,
- and the filter process will also run SUID
- X.L daemon .
- The ownerships of files,
- etc.,
- which have to be manipulated by filter programs should
- have the appropriate permissions for the
- X.L daemon
- userid.
- X.PP
- There are a set of template filters supplied with the PLP software
- that can be easily modified to meet most common requirements.
- A common method of incorporating new filters is to use a shell
- script as a filter,
- and have the shell script invoke a specialized program with the
- appropriate parameters.
- This techique has a slight penalty in performance,
- but is very quick to implement.
- X.PP
- X.NH 2
- XFilter Program Invocation and Actions
- X.PP
- Output filters are invoked by the queue server daemon,
- and take their input from stdin
- X(file descriptor 0),
- have stdout (file descriptor 1) connected to the output device,
- and stderr (file descriptor 2) connected either to
- X.B lf
- X(log file) or to a data sink (/dev/null).
- Normal completion of the filter results when
- it reads EOF on stdin,
- and should exit with user status 0 if there were no errors.
- It should ignore any SIGPIPE signals.
- A user status 1 indicates that the job did not complete
- normally and should be reprinted,
- and any other status will cause the job to be discarded.
- The filter should also check for successful writes to stdout.
- X.PP
- A filter process runs setuid
- X.I daemon
- and is in the same process group as its creating server process.
- This allows
- X.IR killpg \|(2)
- to kill both the queue server process and any filters it has created.
- XFor example,
- X.I lprm
- terminates a running queue handler by
- sending a SIGINT signal to the queue servers process group using
- X.I killpg.
- This signal can be trapped by filters which need
- to perform cleanup operations such as
- deleting temporary files.
- X.NH 2
- XFilter Parameters and Invocation
- X.PP
- XFilters are invoked with a set of parameters determined by the
- entries in the printcap,
- their intended purpose,
- and other actions.
- XFigure 7.1 is an example of a filter specification.
- X.KF
- X.in +1i
- X.nf
- X.DT
- X.L
- X.SM
- X# Versatec Printer, Lind 33
- X# Patrick Powell, 3 Nov 87
- X# Uses the new filters
- versatec\||\|versatec_lind33:\e
- X :fx=flpdt:mx#2000:\e
- X :lp=/dev/va0:sd=/usr/spool/versatec_lind33:\e
- X :af=/usr/adm/vaacct:\e
- X :of=/usr/lib/vpf -v3 -m '-K prefix \e013\e015':
- X.LG
- X.in -1i
- X.R
- X.ce
- XFigure 7.1. Filter Specification Example
- X.KE
- X.PP
- A filter is invoked with the parameters in Figure 7.2,
- which may be present or missing,
- and in any order.
- The accounting file (if present) will always be the last parameter,
- and is the only one without a
- X.B \-
- prefix.
- X.KF
- X.nf
- X.DT
- X.L
- X.SM
- X.in +1i
- filtername arguments \e
- X -Pprinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \e
- X [-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost \e
- X -Fformat [affile]
- X.R
- X.in -1i
- X.LG
- X.ce
- XFigure 7.2 Filter Arguments
- X.KE
- X.PP
- The
- X.I filtername
- and
- X.I arguments
- values are provided in the printcap filter information.
- Arguments can be quoted and will be passed as a single argument to the
- filter program,
- similar to the method used by the Bourne shell.
- Note that the escape sequences in Figure 7.1 will be translated into
- a single character value,
- and the resulting string will be an arguement for the filter.
- X.PP
- The
- X.B \-P
- X(printer) option is used to pass the printcap entry printer name.
- The
- X.B \-w
- and
- X.B \-l
- options specify the horizontal and vertical page
- size in characters and lines (obtained from the
- X.B pw
- and
- X.B pl
- printcap entries).
- Note that the
- X.L "lpr -wNNN"
- value will be passed if it has been specified by a user as the
- X.B \-w
- option value.
- The
- X.B \-x
- and
- X.B \-y
- options specify the horizontal and vertical page
- size in pixels (from the
- X.B px
- and
- X.B py
- printcap entries).
- The
- X.B \-F
- X(format)
- option specifies the format that this filter is being used for.
- X.PP
- The above parameters are provided for all filters,
- including the OF filter and
- BP and EP banner printing filters.
- The OF filter must detect the character sequence ESC\ ^A
- X(\e031, \e001),
- flush its output,
- and suspend itself using \fIkill\fP\|(\fIgetpid\fP(),\ SIGSTOP).
- The server will then start up other filters,
- and use them to print jobs.
- After the job has been printed,
- the server will signal the OF filter to continue using
- SIGCONT.
- X.PP
- All filters are invoked with the above parameters,
- and the additional ones may be provided depending on functionality.
- The
- X.B \-c
- X(literal) flag is optional,
- and is specified for literal or
- X.B \-l
- output being printed using the
- X.B IF
- filter.
- The
- X.B \-i
- X(indent)
- value is optional,
- and is the value specified by the
- X.B \-i
- option of
- X.I lpr .
- The
- X.B \-Z
- X(extra parameters) are parameters passed to the filter by the
- X.I lpr
- X.B \-Z
- option.
- The
- X.B \-C
- X(class or priority)
- and
- X.B \-J
- X(job name)
- are optional and generated by
- X.IR lpr .
- The
- X.B \-n
- and
- X.B \-h
- parameters specify the login name and host name respectively of the
- originator of the job.
- X.PP
- The last (optional) entry is the name of the
- accounting file,
- taken from the
- X.B af
- printcap entry.
- This may be a default value,
- or specified by the user.
- If the accounting file does not exist or is unable to be opened in
- append mode,
- then accounting action is suppressed.
- X.NH 2
- Banner Printing Filters
- X.PP
- The
- X.B bp
- X(banner printer BP)
- and
- X.B ep
- X(end printer EP)
- entries specify a banner and end printing program that is invoked
- at the start and end of a job.
- The BP and EP filters are invoked with the same parameters as the
- IF filter,
- and with the
- X.B -Ff
- format option.
- Special flags and parameters for these filters may be specified
- in the printcap entry.
- X.PP
- The banner printing programs will have
- their standard input
- X(file descriptor 0) set to
- X.L /dev/null ,
- standard output
- X(file descriptor 1) to the output device,
- and standard error
- X(file descriptor 2)
- to the error logging file.
- They must exit with 0 user status for successful completion;
- any other value indicates unsuccessful completion and the
- and an error reported.
- X.NH 2
- Accounting Information
- X.PP
- Accounting information is appended to the accounting file by the
- appropriate output filter.
- Rather than have a complex binary accounting database,
- this version assumes that accounting information will be simple and easy
- to maintain and understand.
- The
- X.I pac
- program has been supplied to make accounting information easily managable,
- but most accounting procedures can be carried out with a simple
- shell script,
- and a hearty use of
- X.I sort ,
- X.I sed ,
- and
- X.I awk .
- In order to keep track of accounting information,
- it must be maintained in a consistent manner.
- XEntries in the raw accounting file should have the form
- illustrated in
- XFigure 7.3.
- X.KF
- X.L
- X.SM
- X.in +1i
- X.nf
- host user printer format pages date
- attila.cs.umn.edu root imagen_lind22 n 5 Fri May 20 21:29:22 CDT 1988
- X.R
- X.LG
- X.in -1i
- X.ce
- XFigure 7.3 Accounting File Entry
- X.KE
- X.PP
- The host,
- user,
- printer,
- and format
- information
- can be obtained from the parameters passed to the filter.
- The page entry is the number of billable pages.
- When the
- X.I pac
- program produces a summary,
- the summary file has the format as in
- XFigure 7.4.
- X.KF
- X.L
- X.SM
- X.in +1i
- X.nf
- host user printer format pages jobs
- attila.cs.umn.edu root imagen_lind22 n 5 1
- attila.cs.umn.edu root imagen_lind22 l 220 7
- X.R
- X.LG
- X.in -1i
- X.ce
- XFigure 7.4 Summary File Entry
- X.KE
- X.PP
- XExperience has indicated that most sites use a differing approaches
- to accounting,
- with little requirement commonality.
- Thus,
- these accounting procedures and information may be
- added or modified as required.
- Note that the accounting is done by the filter programs,
- and not by the PLP software.
- X.NH 2
- Prefilters
- X.PP
- The
- X.I lpr
- program can use
- X.I prefilters
- to process the text before spooling.
- The prefilters are invoked with the the following arguments,
- which are the same as specified for the output filter.
- X.DS
- X.DT
- X.SM
- X.L
- filtername arguments \e
- X -Pprinter -wwidth -llength -xwidth -ylength [-c] [-iindent] \e
- X [-Zoptions] [-Cclass] [-Jjob] [-Raccntname] -nlogin -hHost \e
- X -Fformat file [files]
- X.R
- X.DE
- X.PP
- The options are specified in exactly the same manner
- as for the filter for the specified format.
- The file names are either those specified to
- X.I lpr
- by the user,
- or a copy of the input from stdin.
- The prefilter must copy these files to stdout,
- performing whatever filter functions are neccessary.
- X.PP
- If successful,
- the prefilter should exit with a 0 user status;
- anything else will indicate failure and the user job will be discarded.
- XErrors written to
- X.L stderr
- will be directed to the
- X.I lpr
- X.L stderr
- output.
- X.NH 2
- Adapting Existing Filters and Writing Filters
- X.PP
- If you have an existing set of filters for the Berkeley LPD
- daemon,
- you can use the
- X.L compat
- program supplied with this package to adapt them to use with PLP.
- This program invokes an OF, IF,
- or other filter with the old Berkeley style of parameters.
- XFor example,
- the following entry printcap
- X.B if
- entry will invoke the
- X.L imfilter
- program to be used as the IF filter.
- X.ti +.5i
- X.L "if=/usr/local/lib/compat /usr/local/lib/imfilter"
- X.PP
- If a new filter is needed,
- you can start with the
- programs supplied with this distribution,
- found in the
- X.I filters
- directory.
- A sample filter would consist of an application independent
- X.L main
- routine which parses the command line input flags
- and calls a user supplied
- X.L filter()
- function,
- and support functions.
- These are available in the
- X.L filter/main.c
- file.
- The
- X.I suspend()
- support routine
- suspends the filter when the appropriate string is detected in the input.
- XError message and termination routines are provided.
- END_OF_FILE
- if test 9734 -ne `wc -c <'doc/PLP/07.t'`; then
- echo shar: \"'doc/PLP/07.t'\" unpacked with wrong size!
- fi
- # end of 'doc/PLP/07.t'
- fi
- if test -f 'src/checkpc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/checkpc.c'\"
- else
- echo shar: Extracting \"'src/checkpc.c'\" \(9770 characters\)
- sed "s/^X//" >'src/checkpc.c' <<'END_OF_FILE'
- X/***************************************************************************
- X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
- X ***************************************************************************
- X * MODULE: checkpc.c
- X * Check out a print cap, and create entries
- X ***************************************************************************
- X * Revision History: Created Tue Mar 1 07:56:38 CST 1988
- X * $Log: checkpc.c,v $
- X * Revision 3.1 88/06/18 09:33:56 papowell
- X * Version 3.0- Distributed Sat Jun 18 1988
- X *
- X * Revision 2.2 88/05/14 10:20:42 papowell
- X * Modified -X flag handling
- X *
- X * Revision 2.1 88/05/09 10:07:42 papowell
- X * PLP: Released Version
- X *
- X * Revision 1.6 88/04/15 13:06:27 papowell
- X * Std_environ() call added, to ensure that fd 0 (stdin), 1 (stdout), 2(stderr)
- X * have valid file descriptors; if not open, then /dev/null is used.
- X *
- X * Revision 1.5 88/04/07 12:30:22 papowell
- X *
- X * Revision 1.4 88/03/25 14:59:05 papowell
- X * Debugged Version:
- X * 1. Added the PLP control file first transfer
- X * 2. Checks for MX during file transfers
- X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
- X * apparently they open files and then assume that they will stay
- X * open.
- X * 4. Made sure that stdin, stdout, stderr was available at all times.
- X *
- X * Revision 1.3 88/03/12 10:03:28 papowell
- X * *** empty log message ***
- X *
- X * Revision 1.2 88/03/11 19:28:12 papowell
- X * Minor Changes, Updates
- X *
- X * Revision 1.1 88/03/01 11:08:16 papowell
- X * Initial revision
- X *
- X ***************************************************************************/
- X#ifndef lint
- static char id_str1[] =
- X "$Header: checkpc.c,v 3.1 88/06/18 09:33:56 papowell Exp $ PLP Copyright 1988 Patrick Powell";
- X#endif lint
- X/*
- X * checkpc: check out the entries in the printcap,
- X * checking to see that the default files and directories are present
- X * or absent as are indicated by the printcap entry.
- X *
- X * checkpc [-l] [-s] [-a] [-o] [-f] [-Pprinter] [printcapfile]
- X * The default is to create all the various files;
- X * the following flags are used to disable automatic creation:
- X * -l - no log file
- X * -s - no status file
- X * -o - no output device
- X * -a - no accounting file
- X * -f - fix, attempt to create with the desired perms
- X * -P printer this printer only
- X * printcapfile: name of the printcap file to be used; default is /etc/printcap
- X */
- X
- X#include "lp.h"
- X
- int noout; /* no output file */
- int nolog; /* no log file */
- int noout; /* no output file */
- int nostat; /* no status file */
- int noacct; /* no accounting file */
- int fix; /* fix if bad or missing */
- struct passwd *pwent, *getpwnam(); /* password entry */
- int DU, DG;
- int canchown; /* can do chown */
- X
- main( argc, argv )
- X int argc;
- X char **argv;
- X{
- X char **prlist;
- X int option;
- X
- X /*
- X * Set fd 0, 1, 2 to /dev/null if not open
- X */
- X Std_environ();
- X /*
- X * set umask to avoid problems with user umask
- X */
- X (void)umask(0);
- X
- X# ifdef XPERIMENT
- X Setup_test();
- X# endif XPERIMENT
- X /*
- X * set up the pathnames for information files
- X */
- X fprintf( stdout, "before printcap '%s'\n", Printcap );
- X Tailor_names();
- X fprintf( stdout, "after printcap '%s'\n", Printcap );
- X
- X while ((option = Getopt( argc, argv, "D:afolsXP:" )) != EOF ){
- X switch (option) {
- X case 'D': /* turn on Debugging */
- X if( Optarg ){
- X Debug = atoi( Optarg );
- X }
- X break;
- X default:
- X usage();
- X break;
- X case 'a': /* no acct file */
- X ++noacct;
- X break;
- X case 'f': /* no acct file */
- X ++fix;
- X break;
- X case 'o': /* no output file */
- X ++noout;
- X break;
- X case 'l': /* no log file */
- X ++nolog;
- X break;
- X case 's': /* no status file */
- X ++nostat;
- X break;
- X case 'X': /* Test version */
- X# ifdef DEBUG
- X Setup_test();
- X Tailor_names();
- X# else
- X usage();
- X# endif DEBUG
- X break;
- X case 'P': /* printer */
- X if( Optarg ){
- X Printer = Optarg;
- X } else {
- X usage();
- X }
- X break;
- X }
- X }
- X if( Optind < argc ){
- X (void)strcpy(Printcap, argv[Optind]);
- X ++Optind;
- X }
- X if( Optind < argc ){
- X usage();
- X }
- X
- X canchown = (geteuid() == 0 );
- X
- X if( canchown == 0 ){
- X (void)fprintf(stdout, "%s: not running root\n", Name );
- X (void)fflush(stdout);
- X }
- X
- X if((pwent = getpwnam(DAEMON) ) == NULL){
- X logerr_die( XLOG_DEBUG, "getpwnam failed for daemon" );
- X }
- X DU = pwent->pw_uid;
- X DG = pwent->pw_gid;
- X (void)fprintf(stdout, "Printcap file: %s\n", Printcap );
- X (void)fflush(stdout);
- X if( Printcap[0] != '/' ){
- X (void)fprintf(stdout, "Printcap file must be absolute path name\n");
- X (void)fflush(stdout);
- X exit(1);
- X }
- X
- X if( Printer ){
- X doprinter();
- X } else {
- X (void)fprintf(stdout, "Doing all printers\n" );
- X (void)fflush(stdout);
- X for(prlist = All_printers(); Printer = *prlist; ++prlist ){
- X doprinter();
- X }
- X }
- X}
- X
- X/*
- X * doprinter:
- X * 1. get the printcap entry
- X * 2. check the spool direcotry for ownership, etc.
- X * 3. check the log, accounting, and lock file for existence.
- X */
- doprinter()
- X{
- X if( Get_pc_entry(Printer, All_pc_vars, All_pc_len ) == 0){
- X (void)fprintf(stdout,"no printer %s", Printer );
- X (void)fflush(stdout);
- X return;
- X }
- X (void)fprintf(stdout, "checking printer %s: ", Printer );
- X (void)fflush(stdout);
- X /*
- X * check to see if the spool directory exists
- X */
- X (void)fprintf(stdout, "SD %s, ",SD);
- X (void)fflush(stdout);
- X (void)all_check( 0,S_IFDIR, SD, 0755, "daemon", "daemon" );
- X if( chdir( SD ) < 0 ){
- X logerr( XLOG_DEBUG, "cannot chdir to SD" );
- X return;
- X }
- X if( noout == 0 && LP && *LP ){
- X (void)fprintf(stdout, "LP %s, ",LP);
- X (void)fflush(stdout);
- X (void)all_check( noout,S_IFREG, LP, 0644, "daemon", "daemon" );
- X }
- X if( nolog == 0 && LF && *LF ){
- X (void)fprintf(stdout, "LF %s, ",LF);
- X (void)fflush(stdout);
- X (void)all_check( nolog,S_IFREG, LF, 0664, "daemon", "daemon" );
- X }
- X if( LO && *LO ){
- X (void)fprintf(stdout, "LO %s, ",LO);
- X (void)fflush(stdout);
- X (void)all_check( 0,S_IFREG, LO, 0644, "daemon", "daemon" );
- X }
- X if( noacct || AF == 0 || *AF == 0 ){
- X (void)fprintf(stdout, "no AF, ");
- X (void)fflush(stdout);
- X } else {
- X (void)fprintf(stdout, "AF %s, ",AF);
- X (void)fflush(stdout);
- X (void)all_check( noacct,S_IFREG, AF, 0664, "daemon", "daemon" );
- X }
- X if( nostat == 0 && ST && *ST ){
- X (void)fprintf(stdout, "ST %s, ",ST);
- X (void)fflush(stdout);
- X (void)all_check( nostat,S_IFREG, ST, 0664, "daemon", "daemon" );
- X }
- X if( PS && *PS ){
- X (void)fprintf(stdout, "PS %s, ",PS);
- X (void)fflush(stdout);
- X (void)all_check( nostat,S_IFREG, PS, 0664, "daemon", "daemon" );
- X }
- X (void)fprintf(stdout, "\n" );
- X (void)fflush(stdout);
- X}
- X
- X/*
- X * check and fix if necessary
- X */
- all_check(remove,type,path,perms, owner, group)
- X int type; /* S_IFDIR or S_IFREG */
- X char *path; /* pathname of thing */
- X int perms; /* perms for the file/directory */
- X char *owner, *group;
- X{
- X struct stat statbuf;
- X char cmd[BUFSIZ];
- X int status;
- X int ok;
- X
- X ok = 1;
- X if( stat( path, &statbuf ) < 0 ){
- X logerr( XLOG_DEBUG, "%s cannot be stated", path);
- X if( remove ){
- X return 1;
- X }
- X if( fix ){
- X fixup( type, path, perms, owner, group );
- X }
- X return(0);
- X }
- X if( remove ){
- X (void)fprintf(stdout, "removing %s", path );
- X (void)fflush(stdout);
- X (void)sprintf( cmd, "rm -f %s", path );
- X status = system(cmd);
- X if(status){
- X (void)fprintf(stdout, "fix: %s failed, try by hand\n", cmd);
- X (void)fflush(stdout);
- X exit(1);
- X }
- X }
- X if( (statbuf.st_mode & type) == 0 ){
- X (void)fprintf(stdout,"not a %s ",(type==S_IFDIR)?"directory":"file" );
- X (void)fflush(stdout);
- X return(0);
- X }
- X if( statbuf.st_uid != DU ){
- X ok = 0;
- X (void)fprintf(stdout, "not owner '%s' ",owner );
- X (void)fflush(stdout);
- X if( fix && canchown ){
- X fixup( type, path, perms, owner, group );
- X return 0;
- X }
- X }
- X if( statbuf.st_gid != DG ){
- X ok = 0;
- X (void)fprintf(stdout, "not group '%s' ",group );
- X (void)fflush(stdout);
- X if( fix && canchown ){
- X fixup( type, path, perms, owner, group );
- X return 0;
- X }
- X }
- X if( (statbuf.st_mode & 0777) != perms ){
- X ok = 0;
- X (void)fprintf(stdout, "perms are %o ", (statbuf.st_mode & 0777) );
- X (void)fflush(stdout);
- X if( fix ){
- X fixup( type, path, perms, owner, group );
- X return 0;
- X }
- X }
- X putchar( '\n' );
- X (void)fflush(stdout);
- X return ( ok );
- X}
- X
- X/*
- X * fixup( type, path, perms, owner, group )
- X * -- try to create the file/directory with the appropriate
- X * permissions
- X */
- fixup( type, path, perms, owner, group )
- X int type, perms;
- X char *path, *owner, *group;
- X{
- X int status;
- X char cmd[BUFSIZ];
- X struct stat statbuf;
- X
- X (void)fprintf(stdout, "trying to fix %s %s\n",(type==S_IFDIR)?"directory":"file",path);
- X (void)fflush(stdout);
- X if( type==S_IFDIR ){
- X (void)sprintf( cmd, "mkdir %s", path );
- X } else {
- X (void)sprintf( cmd, "touch %s", path );
- X }
- X (void)fprintf(stdout, "fix: %s\n", cmd );
- X (void)fflush(stdout);
- X status = system( cmd );
- X if( stat( path, &statbuf ) < 0 ){
- X (void)fprintf(stdout, "cannot stat %s, you have to try by hand\n", path );
- X (void)fflush(stdout);
- X }
- X /*
- X * fix up ownership and perms, you are root
- X */
- X if( canchown ){
- X (void)sprintf(cmd, "chown %s %s", owner, path );
- X (void)fprintf(stdout, "fix: %s\n", cmd );
- X (void)fflush(stdout);
- X status = system( cmd );
- X if(status){
- X (void)fprintf(stdout, "fix: %s failed, try by hand\n", cmd);
- X }
- X (void)sprintf(cmd, "chgrp %s %s", group, path );
- X (void)fprintf(stdout, "fix: %s\n", cmd );
- X (void)fflush(stdout);
- X status = system( cmd );
- X if(status){
- X (void)fprintf(stdout, "fix: %s failed, try by hand\n", cmd);
- X }
- X }
- X (void)sprintf(cmd, "chmod %o %s", perms, path );
- X (void)fprintf(stdout, "fix: %s\n", cmd );
- X (void)fflush(stdout);
- X status = system( cmd );
- X if(status){
- X (void)fprintf(stdout, "fix: %s failed, try by hand\n", cmd);
- X }
- X}
- X
- usage()
- X{
- X (void)fprintf(stdout,
- X "use: %s [-aflso][-Pprinter] [printcapfile]", Name);
- X (void)fflush(stdout);
- X exit(1);
- X}
- X
- cleanup()
- X{ ; }
- END_OF_FILE
- if test 9770 -ne `wc -c <'src/checkpc.c'`; then
- echo shar: \"'src/checkpc.c'\" unpacked with wrong size!
- fi
- # end of 'src/checkpc.c'
- fi
- if test -f 'src/remoteprinter.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/remoteprinter.c'\"
- else
- echo shar: Extracting \"'src/remoteprinter.c'\" \(9823 characters\)
- sed "s/^X//" >'src/remoteprinter.c' <<'END_OF_FILE'
- X/***************************************************************************
- X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
- X ***************************************************************************
- X * MODULE: remoteprinter.c
- X * send a job to a remote Printer
- X ***************************************************************************
- X * Revision History: Creation Fri Jan 15 19:28:22 CST 1988
- X * $Log: remoteprinter.c,v $
- X * Revision 3.1 88/06/18 09:35:31 papowell
- X * Version 3.0- Distributed Sat Jun 18 1988
- X *
- X * Revision 2.3 88/05/14 10:18:22 papowell
- X * Use long format for job file names;
- X * Added 'fd', no forward flag;
- X * Control file has to have hostname and origination agree.
- X *
- X * Revision 2.2 88/05/11 09:52:49 papowell
- X * Remote printer file transfer error fixed.
- X *
- X * Revision 2.1 88/05/09 10:10:04 papowell
- X * PLP: Released Version
- X *
- X * Revision 1.4 88/04/06 12:12:35 papowell
- X * Minor updates, changes in error message formats.
- X * Elimination of the AF_UNIX connections, use AF_INET only.
- X * Better error messages.
- X *
- X * Revision 1.3 88/03/25 15:01:27 papowell
- X * Debugged Version:
- X * 1. Added the PLP control file first transfer
- X * 2. Checks for MX during file transfers
- X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
- X * apparently they open files and then assume that they will stay
- X * open.
- X * 4. Made sure that stdin, stdout, stderr was available at all times.
- X *
- X * Revision 1.2 88/03/12 10:03:32 papowell
- X * *** empty log message ***
- X *
- X * Revision 1.1 88/03/01 11:09:10 papowell
- X * Initial revision
- X *
- X ***************************************************************************/
- X#ifndef lint
- static char id_str1[] =
- X "$Header: remoteprinter.c,v 3.1 88/06/18 09:35:31 papowell Exp $ PLP Copyright 1988 Patrick Powell";
- X#endif lint
- X
- X#include "lp.h"
- X
- X/***************************************************************************
- X * int Setup_xfer()
- X * sends the "\02Printer" message to the remote Host
- X * Returns: successful JSUCC, otherwise JFAIL
- X ***************************************************************************/
- int
- Setup_xfer()
- X{
- X char buf[BUFSIZ];
- X
- X if( RP == 0 || *RP == 0 ){
- X fatal(XLOG_INFO, "no RP specified for RM (%s)", RM );
- X }
- X (void)sprintf( buf, "%c%s\n", REQ_RECV, RP );
- X if(Debug>3)log(XLOG_DEBUG,
- X "Setup_xfer: request %d, (REQ_RECV) Host '%s' pr '%s'",
- X REQ_RECV,RM,RP);
- X if( JSUCC == Link_line( -1, buf )){
- X if(Debug>3)log(XLOG_DEBUG,"Setup_xfer: request sent");
- X if( JSUCC == Link_confirm()){
- X if(Debug>3)log(XLOG_DEBUG,"Setup_xfer: request to %s confirmed",RM);
- X return(JSUCC);
- X }
- X if(Debug>3)log(XLOG_DEBUG,"Setup_xfer: request to %s not confirmed",RM);
- X } else {
- X if(Debug>3)log(XLOG_DEBUG,"Setup_xfer: request not sent");
- X }
- X setstatus("request for file transfer to %s failed %s", RM, Time_str() );
- X fatal( XLOG_INFO, "Setup_xfer: cannot start transfer to %s", RM );
- X /*NOTREACHED*/
- X}
- X
- X/***************************************************************************
- X * Sendjob( FILE *cfp; struct queue *q)
- X * 1. First scan extracts information which controls printing
- X * and finds the names of the files to send.
- X * 2. The data files are then sent.
- X * 3. Control file is then sent.
- X * 4. Job files are removed
- X * 5. Control file is removed
- X * Returns: JBUSY, JFAIL, JSUCC, JABORT
- X * NOTE: this code was based on a description of the LPD file transfer
- X * protocol.
- X *
- X * File transfer protocol:
- X * Sender: sends line of form 'flag' length filename
- X * Receiver: acknowledges with 0 (single byte)
- X * Sender: sends file (length bytes of information), then a teminating 0
- X * Receiver: acknowledges with 0 (single byte)
- X *
- X * Tne end is signalled by closing the stream, which results in a read error.
- X *
- X *************************************************************************/
- Sendjob(cfp, q)
- X FILE *cfp; /* control file */
- X struct queue *q; /* job entry */
- X{
- X FILE *fp; /* File to send */
- X char parm[MAXPATHLEN]; /* holds a line read in */
- X char *arg; /* control line argument */
- X char opt; /* control line option */
- X int jstatus; /* job status */
- X int i; /* ACME Integers, Inc. */
- X
- X /*
- X * set job status
- X */
- X jstatus = JFAIL; /* default */
- X
- X /*
- X * read the control file and extract user information
- X */
- X Parmcount = 0;
- X while(fgets( parm, sizeof(parm), cfp )){
- X if( (arg = index(parm, '\n')) == 0 ){
- X log( XLOG_INFO, "Sendjob: bad control file format (%s), no endline",
- X q->q_name);
- X jstatus = JABORT;
- X goto error;
- X }
- X *arg = 0;
- X opt = parm[0];
- X arg = parm+1;
- X if( !isascii(opt) || !isalnum( opt ) || strlen( arg ) > MAXPARMLEN ){
- X log( XLOG_INFO, "Sendjob: bad control file (%s), line(%s)",
- X q->q_name,parm);
- X jstatus = JABORT;
- X goto error;
- X }
- X if( !islower( opt ) && opt != 'U' ){
- X continue;
- X }
- X if( Job_match( q->q_name, arg ) == 0 ){
- X log( XLOG_INFO, "Sendjob: bad file name format (%s)", arg );
- X jstatus = JABORT;
- X goto error;
- X }
- X if( islower( opt )){
- X if( Add_name(arg) < 0 ){
- X log( XLOG_INFO, "Sendjob: too many files (%s)", arg );
- X jstatus = JABORT;
- X goto error;
- X }
- X } else {
- X if( (i = Find_name(arg) ) < 0 ){
- X log(XLOG_INFO,"Sendjob: job(%s)U specified for '%s' not in job",
- X q->q_name,parm);
- X jstatus = JABORT;
- X goto error;
- X }
- X }
- X }
- X /*
- X * We send the control file first if we are using the PLP protocol
- X */
- X if( FJ ){
- X jstatus = sendfile( cfp, q->q_name, CNAME);
- X if( jstatus != JSUCC ){
- X setstatus("transfer %s to %s failed %s",q->q_name,RM,Time_str());
- X log(XLOG_INFO,"Sendjob: sendname %s to %s failed",q->q_name,RM);
- X goto error;
- X }
- X }
- X /*
- X * send the jobs in the file
- X */
- X for( i = 0; i < Parmcount; ++i ){
- X arg = Parms[i].filename;
- X if( (fp = fopen_daemon( arg, "r" )) == NULL ){
- X jstatus = JABORT;
- X logerr( XLOG_INFO,"Sendjob: cannot open data file %s",arg);
- X goto error;
- X }
- X /*
- X * send the file
- X */
- X if(Debug>3)log(XLOG_DEBUG,"Sendjob: sending file %s", arg );
- X jstatus = sendfile( fp, arg, DFILE );
- X (void)fclose(fp);
- X if( jstatus != JSUCC ){
- X setstatus("transfer %s to %s failed %s",arg,RM,Time_str());
- X log(XLOG_INFO,"Sendjob: transfer %s to host %s failed",arg,RM);
- X goto error;
- X }
- X }
- X /*
- X * send the control file
- X */
- X if(Debug>3)log(XLOG_DEBUG,"sending file %s", q->q_name );
- X if( FJ ){
- X jstatus = sendname( cfp, q->q_name, CEND );
- X } else {
- X jstatus = sendfile( cfp, q->q_name, CFILE );
- X }
- X if( jstatus != JSUCC ){
- X setstatus("transfer %s to %s failed %s",q->q_name,RM,Time_str());
- X log(XLOG_INFO,"Sendjob: transfer %s to host %s failed",q->q_name,RM);
- X goto error;
- X }
- X /*
- X * finished!
- X */
- X jstatus = JSUCC;
- error:
- X if( jstatus != JSUCC ){
- X Link_close();
- X }
- X return (jstatus);
- X}
- X
- X/***************************************************************************
- X * sendfile( FILE* fp; char *name; int flag )
- X * sendfile protocol:
- X * 1. line containing the flag, number of bytes, and file name is sent.
- X * This has the format:
- X * "%c%d %s", flag, filesize, name
- X * DFILE (data file) flag is 03, a CFILE (control file) flag is 02
- X * 2. the remote end responds by sending back a single 0 character;
- X * anything else is an error condition and terminates transfer
- X * 3. the file is then copied to the remote end and terminated with 0
- X * 4. if an error is detected, we send a non-zero character
- X * and close the link.
- X ***************************************************************************/
- X
- sendfile( fp, name, flag )
- X FILE *fp;
- X char *name;
- X int flag;
- X{
- X int succ; /* ACME Integer, Inc. */
- X struct stat statb; /* status buffer */
- X
- X /*
- X * stat the file
- X */
- X if( fstat( fileno(fp), &statb) < 0 ){
- X logerr( XLOG_INFO, "sendname: could not stat %s", name );
- X return( JFAIL );
- X }
- X /*
- X * rewind the file
- X */
- X if( fseek(fp, 0L, 0) < 0 ){
- X logerr_die( XLOG_INFO, "sendfile: fseek failed '%s'", name );
- X }
- X succ = sendname( fp, name, flag );
- X if( succ == JSUCC ){
- X succ = Link_copy( fp, (long)statb.st_size, name );
- X }
- X if( succ == JSUCC ){
- X succ = Link_ack( 0 );
- X }
- X if( succ == JSUCC ){
- X succ = Link_confirm();
- X }
- X if( succ != JSUCC ){
- X succ = JFAIL;
- X Link_close();
- X }
- X return( succ );
- X}
- X
- X/***************************************************************************
- X * Send_error()
- X * Called when you have retried a couple of times; bad job, needs attention
- X ***************************************************************************/
- void
- Send_error()
- X{
- X log(XLOG_CRIT, "job cannot be sent from %s to %s", Host, RM );
- X exit( 0 );
- X}
- X
- X/***************************************************************************
- X * sendname( FILE *fp; char *name; int flag )
- X * sendname protocol:
- X * 1. line containing the flag and file name is sent
- X * This has the format:
- X * "%c%d %s", flag, filesize, name
- X * DFILE (data file) flag is 03, a CFILE (control file) flag is 02
- X * 2. the remote end responds by sending back a single 0 character;
- X * anything else is an error condition and terminates transfer
- X ***************************************************************************/
- sendname( fp, name, flag )
- X FILE *fp;
- X char *name;
- X int flag;
- X{
- X struct stat statb; /* status buffer */
- X int succ; /* ACME Integer, Inc. */
- X char buf[BUFSIZ];
- X
- X /*
- X * stat the file
- X */
- X if( fstat( fileno(fp), &statb) < 0 ){
- X logerr( XLOG_INFO, "sendfile: could not stat %s", name );
- X return( JFAIL );
- X }
- X (void)sprintf( buf, "%c%d %s\n", flag, statb.st_size, name);
- X succ = Link_send( buf );
- X if( succ == JSUCC ){
- X succ = Link_confirm();
- X }
- X return( succ );
- X}
- X
- X/***************************************************************************
- X * Allsent( )
- X * all files have been sent; send a closing 0 and shut down link
- X ***************************************************************************/
- void
- Allsent()
- X{
- X (void)Link_ack( 0 );
- X Link_close();
- X}
- END_OF_FILE
- if test 9823 -ne `wc -c <'src/remoteprinter.c'`; then
- echo shar: \"'src/remoteprinter.c'\" unpacked with wrong size!
- fi
- # end of 'src/remoteprinter.c'
- fi
- if test -f 'src/startprinter.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/startprinter.c'\"
- else
- echo shar: Extracting \"'src/startprinter.c'\" \(10002 characters\)
- sed "s/^X//" >'src/startprinter.c' <<'END_OF_FILE'
- X/***************************************************************************
- X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
- X ***************************************************************************
- X * MODULE: Startprinter.c
- X * Printer queue job handler
- X *
- X * StartPrinter is responsible for handling the Printer queue.
- X * 1. Get the printcap entry.
- X * 2. Check the spool directory to see if printing is enabled
- X * 3. Check to see if there are any jobs
- X * 4. If a remote Printer, call remotePrinter()
- X * If a local Printer, call localPrinter()
- X ***************************************************************************
- X * Revision History: Created Sat Feb 13 09:11:38 CST 1988
- X * $Log: startprinter.c,v $
- X * Revision 3.1 88/06/18 09:35:49 papowell
- X * Version 3.0- Distributed Sat Jun 18 1988
- X *
- X * Revision 2.4 88/05/21 10:28:30 papowell
- X * Minor editing
- X *
- X * Revision 2.3 88/05/14 10:18:27 papowell
- X * Use long format for job file names;
- X * Added 'fd', no forward flag;
- X * Control file has to have hostname and origination agree.
- X *
- X * Revision 2.2 88/05/11 09:50:52 papowell
- X * Remote printer file transfer error fixed.
- X *
- X * Revision 2.1 88/05/09 10:10:30 papowell
- X * PLP: Released Version
- X *
- X * Revision 1.6 88/04/27 18:02:36 papowell
- X * The SIGCHLD signal has an odd behaviour on some systems. Modified so that
- X * it will not get set UNLESS processes are started; also, it is reset
- X * to SIG_DFL, not SIG_IGN.
- X *
- X * Revision 1.5 88/04/07 21:24:27 papowell
- X * changed calls of init to (*init)(). Sigh.
- X *
- X * Revision 1.4 88/04/06 12:13:05 papowell
- X * Minor updates, changes in error message formats.
- X * Elimination of the AF_UNIX connections, use AF_INET only.
- X * Better error messages.
- X *
- X * Revision 1.3 88/03/25 15:01:47 papowell
- X * Debugged Version:
- X * 1. Added the PLP control file first transfer
- X * 2. Checks for MX during file transfers
- X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
- X * apparently they open files and then assume that they will stay
- X * open.
- X * 4. Made sure that stdin, stdout, stderr was available at all times.
- X *
- X * Revision 1.2 88/03/11 19:29:20 papowell
- X * Minor Changes, Updates
- X *
- X * Revision 1.1 88/03/01 11:09:24 papowell
- X * Initial revision
- X *
- X ***************************************************************************/
- X#ifndef lint
- static char id_str1[] =
- X "$Header: startprinter.c,v 3.1 88/06/18 09:35:49 papowell Exp $ PLP Copyright 1988 Patrick Powell";
- X#endif lint
- X
- X#include "lp.h"
- extern int Printjob(), Sendjob();
- extern int Printinit(), Setup_xfer();
- extern void Printfinal(), Printerror(), Allsent(), Send_error();
- X
- Startprinter()
- X{
- X int pid; /* process id */
- X char *ps, *st; /* ACME Pointers */
- X
- X /*
- X * ignore SIGCHILD, explicitly wait for them
- X */
- X (void)signal(SIGCHLD, SIG_DFL);
- X /*
- X * get the printcap entry
- X */
- X if( Get_pc_entry(Printer, All_pc_vars, All_pc_len ) == 0){
- X log( XLOG_INFO, "trying to start non-existent Printer" );
- X exit(0);
- X }
- X if( SS && *SS ){
- X /*
- X * we have a spool server that is to be started
- X */
- X ps = PS;
- X st = ST;
- X if( Set_pc_entry(SS, All_pc_vars, All_pc_len ) == 0){
- X log( XLOG_INFO, "queue %s does not entry", SS );
- X exit(0);
- X }
- X PS = ps;
- X ST = st;
- X LO = Printer;
- X SV = 0;
- X }
- X if( SD == 0 || *SD == 0 ){
- X /*
- X * no spooling directory, not a Printer
- X */
- X if(Debug>0)log(XLOG_DEBUG, "Startprinter: not a Printer");
- X exit(0);
- X }
- X if( RM && NW ){
- X (void)Remote_start();
- X exit(0);
- X }
- X /* chdir to spool directory */
- X if (chdir(SD) < 0) {
- X logerr_die( XLOG_NOTICE,"Startprinter: cannot chdir to %s", SD);
- X }
- X /*
- X * check to see if there is a deamon running
- X */
- X Lfd = Getlockfile( LO, &pid, (char *)0, 0, &LO_statb );
- X if( Lfd == NULL ){
- X if(Debug>2)log(XLOG_DEBUG, "Startprinter: server present, pid %u",pid);
- X exit(0);
- X }
- X if( fseek( Lfd, 0L, 0 ) < 0 ){
- X logerr_die( XLOG_INFO, "Startprinter: T1 fseek failed");
- X }
- X /*
- X * check for unspooling enabled
- X */
- X if( LO_statb.st_mode & DISABLE_PRINT) {
- X if(Debug>0)log( XLOG_DEBUG,"Startprinter: unspooling disabled");
- X exit(0);
- X }
- X /*
- X * handle multiple servers
- X */
- X if( SV && *SV ){
- X Closelockfile(LO, Lfd );
- X Lfd = 0;
- X Start_server();
- X /*
- X * Check on the status of the queue lock file
- X */
- X Lfd = Getlockfile( LO, &pid, (char *)0, 0, &LO_statb );
- X if( Lfd == NULL ){
- X if(Debug>2)log(XLOG_DEBUG, "Startprinter: server present, pid %u",pid);
- X exit(0);
- X }
- X }
- X /*
- X * set up log file
- X */
- X if( fseek( Lfd, 0L, 0 ) < 0 ){
- X logerr_die( XLOG_INFO, "Startprinter: T2 fseek failed");
- X }
- X if(Debug>0)log(XLOG_DEBUG, "Startprinter: should log into %s",
- X LF?LF:"/dev/null");
- X Setuplog( LF, 0 );
- X if( fseek( Lfd, 0L, 0 ) < 0 ){
- X logerr_die( XLOG_INFO, "Startprinter: T3 fseek failed");
- X }
- X /*
- X * OK, you are the server, go to it.
- X * set process group to the queue handler process
- X */
- X (void) setpgrp(0, getpid());
- X
- X Setlockfile( LO, Lfd, getpid(), "(checking queue)");
- X setstatus( "checking queue at %s", Time_str());
- X
- X /*
- X * search the spool directory for work and sort by queue order.
- X */
- X if(Debug>0)log(XLOG_DEBUG, "Startprinter: unqueueing jobs");
- X if( RM ){
- X unspool(Setup_xfer, Sendjob, Allsent, Send_error);
- X } else {
- X unspool(Printinit, Printjob, Printfinal,Printerror);
- X }
- X if(Debug>2)log( XLOG_DEBUG, "Startprinter: work done" );
- X setstatus( "work done at %s", Time_str() );
- X Closelockfile(LO,Lfd);
- X exit( 0 );
- X}
- X
- X
- X/***********************************************************
- X * unspool( init, jobhandler, closer)
- X *
- X * do{
- X * check queue for new jobs
- X * jobdone = 0
- X * for(n = 0;n < Jobcount; ++n)
- X * if queue needs to be resorted then
- X * set jobdone and break from "for" loop;
- X * while not successful and retry count is less than a limit do
- X * init();
- X * success = jobhandler(job n);
- X * -- note: job can be busy (no action), done successfully,
- X * done unsuccessfully and should be abandoned,
- X * or done unsuccessfully and should be repeated
- X * if action was done then set jobdone and remove job
- X * else call closer();
- X * }while( jobdone )
- X * call closer()
- X ***********************************************************/
- X
- unspool( init, dojob, closer, err )
- X int (*init)();
- X int (*dojob)();
- X void (*closer)();
- X void (*err)();
- X{
- X int n; /* job number */
- X int retries; /* number of retries */
- X int success; /* job success status */
- X struct queue *q; /* job entry */
- X int jobdone; /* job done in this pass */
- X FILE *cfp; /* control file */
- X int init_done; /* initialization done */
- X
- X /*
- X * the big loop
- X */
- X init_done = 0;
- X do{
- X /*
- X * search the spool directory for more work.
- X */
- X Jobcount = Getq();
- X /*
- X * reset "update queue order" flag
- X */
- X if(fstat(fileno(Lfd), &LO_statb ) < 0 ){
- X logerr_die( XLOG_NOTICE,"unspool: cannot stat %s", LO);
- X }
- X if(Debug>5)log(XLOG_DEBUG,"unspool: '%s' perms 0%o",LO,
- X LO_statb.st_mode);
- X if(fchmod(fileno(Lfd), (int)(LO_statb.st_mode & CLEAR_REQUE)) < 0){
- X logerr_die( XLOG_NOTICE,"unspool: cannot chmod '%s'", LO);
- X }
- X jobdone = 0;
- X /*
- X * scan the queue
- X */
- X for(n=0; n < Jobcount; ++n ){
- X q = &Queue[n];
- X /*
- X * lock the control file
- X */
- X if( (cfp = Lockcf(q->q_name) )!= NULL ){
- X Setlockfile( LO, Lfd, getpid(), q->q_name );
- X /*
- X * try printing this file until successful,
- X * number of attempts exceeds limit, or abort
- X * try sending indefinately until successful
- X */
- X success = JFAIL;
- X for( retries = 0;
- X success == JFAIL && retries <= RT;
- X ++retries ){
- X /*
- X * STDIO file error reset, needed on some implementations
- X */
- X clearerr( cfp );
- X /*
- X * seek to the start of the file
- X */
- X if( fseek( cfp, 0L, 0 ) < 0 ){
- X logerr_die(XLOG_INFO,"unspool: fseek failed (%s)",
- X q->q_name );
- X }
- X /*
- X * update status information
- X */
- X if(Debug)log(XLOG_DEBUG,"unspool: doing %s, %d retry",
- X q->q_name,retries);
- X /*
- X * initialize
- X */
- X if( init_done == 0 ){
- X init_done = (*init)();
- X if( init_done != JSUCC ){
- X setstatus( "initialization failure, %s",Last_errormsg);
- X return;
- X }
- X }
- X setstatus( "processing, active job started %s, attempt %d",
- X Time_str(), retries+1);
- X /*
- X * try to print the job
- X */
- X success = (*dojob)(cfp, q);
- X }
- X if(Debug>4)log(XLOG_DEBUG,"unspool: %s status %d", q->q_name,
- X success );
- X if( success == JFAIL ){
- X (*err)();
- X init_done = 0;
- X }
- X jobdone = 1;
- X Remove_job( cfp, q );
- X (void)fclose(cfp);
- X }
- X /*
- X * collect any garbage
- X */
- X Reapchild();
- X }
- X /*
- X * collect any garbage
- X */
- X Reapchild();
- X } while( jobdone );
- X /*
- X * collect any garbage
- X */
- X Reapchild();
- X /*
- X * queue finished
- X */
- X if(Debug>0)log(XLOG_DEBUG, "unspool: no more work to do" );
- X (*closer)();
- X}
- X
- X/***************************************************************************
- X * Start_server()
- X * start multiple servers for a single queue. The SV printcap parameter
- X * has a list of the servers. These servers use the spool queues
- X * directory, and have a lock file in the server directory.
- X * This routine will extract the names of each server, fork a process
- X * for it, and then will read the printcap information for the server
- X * from the queue.
- X * The printer names are separated by commas.
- X ***************************************************************************/
- X
- Start_server()
- X{
- X char *ps;
- X char *last;
- X int pid;
- X
- X last = 0;
- X ps = SV;
- X while( ps ){
- X Printer = ps;
- X if( last = index( ps, ',' ) ){
- X *last = 0;
- X ps = last+1;
- X } else {
- X ps = 0;
- X }
- X if( ps ){
- X if( (pid = fork()) < 0 ){
- X logerr_die( XLOG_INFO, "Start_server: fork failed" );
- X } else if( pid == 0 ){
- X ps = 0;
- X }
- X }
- X }
- X if( Set_pc_entry(Printer, All_pc_vars, All_pc_len ) == 0){
- X fatal( XLOG_INFO, "trying to start non-existent server" );
- X }
- X LO = Printer;
- X if(Debug>3)log(XLOG_DEBUG,"Start_server: started" );
- X}
- END_OF_FILE
- if test 10002 -ne `wc -c <'src/startprinter.c'`; then
- echo shar: \"'src/startprinter.c'\" unpacked with wrong size!
- fi
- # end of 'src/startprinter.c'
- fi
- echo shar: End of archive 7 \(of 16\).
- cp /dev/null ark7isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 16 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-