Recently, BarryK enquired about samba-tng's non-existent smbspool and whether printing through smbclient will work. I've advised him that it is indeed possible to do raw/postcript printing with smbclient and the smbc script (from http://willem.engen.nl/projects/cupssmb/) is what he can use or base upon.
I've taken a closer look at the whole smbspool thingy and have scribbled a drop-in replacement script for smbspool by sending print job(s) to smbclient. This script is loosely based on samba's smbspool internal logics, uses smbspool input parameter format and attempts to mimic smbspool behaviour. This script is designed to work with existing CUPS device URI.
The device URI (Uniform Resource Identifier) format for smbspool is defined as:
- smb://[username[:password]@][workgroup/]server[:port]/printer
Examples:
- 1. smb://PRINTSERVER/HP4V (minimum parameter smb://server/printer)
2. smb://192.168.1.2/ML1200 (same as #1 but using IP address)
3. smb://zigbert:ladiesman217@/192.168.2.22:9191/MP250 (extended parameters with username, password and server port)
4. smb://dogbert:majesty@SYHDP/DILBERT/LEDCOPIER (extended parameters with username, password and domain name)
Code: Select all
#!/bin/sh
# Patriot July 2010. GPLv2
# smbspool drop-in replacement script (via smbclient) for CUPS
# This software is not subject to any export provision of the United States
# Department of Commerce, and may be exported to any country or planet.
# Without parameters, assume a CUPS backend query
if [ -z "$1" ]; then
echo 'network smb "Unknown" "Windows Printer via SAMBA (smbclient)"'
exit 0
fi
function errmsg()
{
echo -e "\nUsage: $0 [DEVICE_URI] job-id user title copies options [file]\n"
echo -e "The DEVICE_URI environment variable contains the destination printer," >&2
echo -e "smb://[username[:password]@][workgroup/]server[:port]/printer\n" >&2
[ $1 -eq 0 ] && echo -e "Error: invalid parameter count" >&2
[ $1 -eq 1 ] && echo -e "Error: malformed URI header" >&2
[ $1 -eq 2 ] && echo -e "Error: malformed URI block" >&2
exit 1
}
# Validate parameter count n, 5 =< n <= 6
[ -z "$5" -o "$7" ] && errmsg 0
# Validate DEVICE_URI header
[ "${DEVICE_URI:0:6}" != "smb://" ] && errmsg 1
# Validate DEVICE_URI block
pdev_uri_slash=$(echo $DEVICE_URI| tr -d "/")
let pdev_uri_wc=${#DEVICE_URI}-${#pdev_uri_slash}
[ $pdev_uri_wc -lt 3 -o $pdev_uri_wc -gt 4 ] && errmsg 2
# Retrieve parameters
job_id="$1"; user="$2"; title="$3"; copies="$4"; options="$5"; job_file="$6"
# Parse the DEVICE_URI
pdev_uri=${DEVICE_URI:6}
if [ $pdev_uri_wc -eq 4 ]; then
# parse workgroup/domain
pdev_upw=${pdev_uri%%/*}
pdev_workgroup=${pdev_upw#*@}
if [ ${#pdev_workgroup} -ne ${#pdev_upw} ]; then
pdev_upw=${pdev_upw%@*}
else
pdev_upw=${pdev_upw%@}
pdev_workgroup=
fi
# parse username/password
username=${pdev_upw%:*}
if [ ${#username} -eq ${#pdev_upw} ]; then
password=""
else
password=${pdev_upw#*:}
fi
pdev_uri=${pdev_uri#*/}
fi
# parse server, port & printer
pdev_server=${pdev_uri%/*}
pdev_printer=${pdev_uri#*/}
pdev_port=${pdev_server#*:}
if [ ${#pdev_port} -eq ${#pdev_server} ]; then
pdev_port=
else
pdev_server=${pdev_server%:*}
fi
# Prep extra parameters
extra=
[ "$password" ] || extra="-N "
[ "$pdev_port" ] && extra="${extra}-P $pdev_port "
[ "$pdev_workgroup" ] && extra="${extra}-W $pdev_workgroup "
# Prep credentials
orgUSER=$USER
if [ "$username" ]; then
export USER="$username"
else
export USER="guest"
fi
if [ "$password" ]; then
export PASSWD="$password"
fi
# Prep command set
cmd_set=""
if [ -z "$job_file" ]; then
# assume printing from stdin
pqdata="/tmp/smbrpd-$job_id.$title"
cat > "$pqdata"
else
pqdata="$job_file"
fi
for i in $(seq $copies)
do
# Make copies ?
cmd_set=$cmd_set'print "'$pqdata'" ;'
done
# TODO: Check printer connection online?
# Send the stuff through smbclient
PrnResult=$(smbclient "//$pdev_server/$pdev_printer" ${extra} -c "$cmd_set" 2>&1; echo -e "\nSMBEXIT=$?")
# Cleanups
export USER=$orgUSER
[ "$PASSWD" ] && unset PASSWD
[ -z "$job_file" -a -e "$pqdata" ] && rm -f "$pqdata"
# Set exit status for CUPS
exitStat=$(echo "$PrnResult" | grep 'SMBEXIT'); exitStat=${exitStat#*=}
if [ $exitStat -eq 0 ]; then
echo "SUCCESS: $PrnResult" >&2
else
echo "ERROR!: $PrnResult" >&2
exit 2
fi
exit 0
- Fully supports smb URI format. This allows the authentication details to be embedded within the URI.
- Allows printing to multiple authenticated servers without mucking with separate authentication files.
- Supports print copies option, if required.
- Supports smbclient from both samba and samba-tng.
Manual installation:
1. Save the script as /usr/lib/cups/backend/smb.
2. Give it an owner only permission (# chmod 700 /usr/lib/cups/backend/smb). (If you skip this, smbclient will bork reading smb.conf file)
3. Configure smb printer if required & do a test print
Automatic installation:
1. Install the pet file. The script will be at /usr/lib/cups/backend.
2. Configure smb printer if required & do a test print
Final notes:
- This script is designed to run on puppy >= 4.0 platform with cups >= 1.1.x.
- Development and testing is done on puppy412 with cups-1.3.11, samba-3.0.37 and samba-tng-0.5rc1
- and yes, if anyone's wondering, I am able to print raw/ps using either samba or samba-tng smbclient.
Rgds
._.