Setting up CUPS to spool to a file
pipitas
k1pfeifle at gmx.net
Thu Oct 14 16:50:45 PDT 2004
Kirk Haderlie wrote:
> Is it possible to set CUPS up to spool to a file instead of send the
> output to the printer? We have a RIP product we would like to run the
> file through and have that that application send the final output to the
> printer. We could write a filter to achieve this, but if CUPS can
> already spool the file to disk it would be nice to use that.
>
> The workflow would be CUPS -> File -> RIP -> Printer.
You can enable a very simple file:/ backend by putting "FileDevice
Yes" into cupsd.conf. However it will not allow raw printing of
application/octet-stream files. And the second job will overwrite
the first one (because you need to give a filename to the backend,
in the device URI, like "file:/tmp/print.prn")
You could write your own CUPS backend. Here are the rules for
that:
* make sure it can read from SDIN and write to STDOUT
* make sure if called with zero arguments it responds with
a message similar to the other backends (see how they do it)
* make sure it takes the 5 or 6 arguments all CUPS filters and
backends take in the same order, i.e.
backendname job-id user title copies options [job-file]
* put it into /usr/lib/cups/backend/ and restart cupsd (check
if it is recognized with "lpinfo -v")
You can write it in Bash, Perl, C, Python or whatever you like.
A very simple "filewrite" backend looks like this:
-----------------------------------------------------------------------------
#!/bin/bash
TARGETFILE=${DEVICE_URI#filewrite:}1
if [ $# -eq 0 ]; then
echo "direct filewrite \"Unknown\" \"Print any job to file specified in device-URI\""
exit 0
fi
cat $6 > $TARGETFILE
-----------------------------------------------------------------------------
A more advanced one is here:
--- snip --------------------------------------------------------------------
#!/bin/bash
#
# (c) Kurt Pfeifle, Danka Deutschland GmbH
#
# This simple CUPS backend allows you to "print to file". Install a
# printer like this:
#
# cp <this.file> /usr/lib/cups/backend/filewrite;
# chmod a+x /usr/lib/cups/backend/filewrite;
# /etc/init.d/cups stop;
# /etc/init.d/cups start;
# lpadmin -p fileprinter -v filewrite:/tmp/my_print_testfile.prn -E -P /path/to/PPD
# (you can leave aside the "-P" option to create a "raw" printqueue without filtering)
#
# If you print to the new "fileprinter" printer, you will find the files your
# CUPS filtering produced in "tmp/my_print_testfile.prn".
#
# The filewrite backend is useful for debugging purpuses....
# test for 5 or 6 parameters
FILE=$6 || FILE="-";
LOG=/tmp/filewrite.log; export LOG ;
JOBID=$1 ;
USER=$2 ;
TITLE=$3 ;
COPIES=$4 ;
OPTIONS=$5 ;
PID=$$ ;
echo ${FILE} >> ${LOG} ;
echo ${JOBID} >> ${LOG} ;
echo ${USER} >> ${LOG} ;
echo ${TITLE} >> ${LOG} ;
echo ${COPIES} >> ${LOG} ;
echo ${OPTIONS} >> ${LOG} ;
# if there are no arguments: print the "I'm here" message for cupsd's probing
if [ $# -eq 0 ]; then
echo "direct filewrite \"Unknown\" \"Print any job to file specified in device-URI\""
exit 0
fi
# in case of wrong number of arguments: print usage hint
if [ $# -ne 5 -a $# -ne 6 ]; then
echo ""
echo "Usage: filewrite job-id user title copies options [file]"
echo " example for device-URI: 'filewrite:/path/to/targetfile'"
echo "(this writes the printfile to disk at specified path)"
echo ""
echo "Install a printqueue with 'lpadmin -p <filewriter-printer-name> \
-v filewrite:/</path/to/targetfile> -E [-P /path/to/PPD]"
echo ""
exit 1
fi
# sanitize $TITLE -- remove any spaces, colons and slashes or
# backslashes from filename
TITLE=`echo ${TITLE} | tr [:blank:] _ | tr : _ | tr / _ | tr "\134" _`;
# we should now have a sanitized ${TITLE} to use with less danger of
# screwing things up should we print from a browser or some such....
# get file to which the job is "printed" from device URI, so
# so that you can use this backend multiple times, for various
# "filewrite" printers...
TARGETFILE=${DEVICE_URI#filewrite:}
### uncomment&modify the following line if you need the JOBTITLE,
### USERNAME, JOBID, DATE as part of the filename...
#TARGETFILE=${DEVICE_URI#filewrite:}-${TITLE}-${JOBID}-${USER}
# but check "accepting" status first...
GREPSTRING="not accepting" ;
if lpstat -a $TARGETFILE | grep "$GREPSTRING" &> /dev/null ; then
echo "ERROR: printer $TARGETFILE not accepting jobssss...."
exit 1
fi
# now do the job....
cat $FILE > $TARGETFILE
# just to show you how cupsd logs stuff....
echo "INFO: just a dummy string for the logfile....">&2
echo "ERROR: another dummy string for the logfile....">&2
exit 0
---- snap -------------------------------------------------------------------
A more advanced "dirwrite" would write into a target directory
that you specify as a device URI like here "dir:/tmp/cupsfiles/"
The magic line for this would be to use
TARGETFILE=${DEVICE_URI#dir:}
You could also write a "postprocess" backend which would basically
consist of an outgoing pipe that directly inputs the CUPS output
to another command (which of course must take input from STDIN),
with the "magic line":
cat $6 | TARGETPROG -
where your backend uses
device-URI postproc:/path/to/your/program
TARGETPROG=${DEVICE_URI#postproc:}
Hope this helps,
Kurt
More information about the cups-devel
mailing list