diff --git a/cups.spec b/cups.spec index 6518791..db9c862 100644 --- a/cups.spec +++ b/cups.spec @@ -12,6 +12,7 @@ Group: System Environment/Daemons Source: ftp://ftp.easysw.com/pub/cups/test//cups-%{version}-source.tar.bz2 Source1: cups.init Source2: cupsprinter.png +Source3: http://www.openprinting.org/download/printing/dnssd Source4: pstopdf Source5: cups-lpd Source6: pstoraster @@ -184,6 +185,9 @@ mkdir -p $RPM_BUILD_ROOT%{initdir} make BUILDROOT=$RPM_BUILD_ROOT install +# Include Till Kamppeter's dnssd backend. +install -m 755 %{SOURCE3} $RPM_BUILD_ROOT%{cups_serverbin}/backend/dnssd + # Serial backend needs to run as root (bug #212577). chmod 700 $RPM_BUILD_ROOT%{cups_serverbin}/backend/serial @@ -440,6 +444,7 @@ rm -rf $RPM_BUILD_ROOT %changelog * Wed Sep 19 2007 Tim Waugh 1:1.3.2-1 +- Include Till Kamppeter's dnssd backend. - 1.3.2. - No longer need str2512 patches. diff --git a/dnssd b/dnssd new file mode 100644 index 0000000..af4c35e --- /dev/null +++ b/dnssd @@ -0,0 +1,207 @@ +#!/usr/bin/perl +# The above Perl path may vary on your system; fix it!!! -*- perl -*- + +# dnssd - Search for network printers with the avahi-browse command +# (Zeroconf, DNS-SD) + +# Printer discovery CUPS backend (like the SNMP backend) +# See also http://qa.mandriva.com/show_bug.cgi?id=21812 + +# Copyright 2007 Till Kamppeter +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 of the License, or (at your +# option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, +# USA. + +# Usage: +# +# cp dnssd /usr/lib/cups/backend/ +# chmod 755 /usr/lib/cups/backend/dnssd +# killall -HUP cupsd (or "/etc/init.d/cups restart", CUPS 1.1.x only) +# lpinfo -v (or use any printer setup tool) + +#use strict; + +$0 =~ m!^(.*)/([^/]+)\s*$!; +my $progname = ($2 || $0 || "dnssd"); +my $progpath = ($1 || "/usr/lib/cups/backend"); + +if ($ARGV[0]){ + die "This backend is only for printer discovery, not for actual printing.\n"; +} + +my $avahicmd = "avahi-browse -k -t -v -r -a 2> /dev/null"; + +# IPs which are for computers, consider their printer entries as queues +# set up with the local printing system (CUPS, LPD, Windows/Samba SMB, ...) +my @ipblacklist = (); +my $output; +my ($interface, $nettype, $ip, $host, $make, $model, $description, $cmd, $makemodel, $deviceid, $protocol, $port, $uriext, $uri); + +open (AVAHI, "$avahicmd |") or die "Could not call \"$avahicmd\"\n"; +while (my $line = ) { + chomp ($line); + if ($line =~ /^\s*=\s+(\S+)\s+(\S+)\s+(.*?)\s+(\S+)\s+(\S+)\s*$/) { + # New item + $interface = $1; + $nettype = $2; + my $itemname = $3; + my $protocolinfo = $4; + if ($protocolinfo =~ /_workstation/) { + $protocol = "computer"; + } elsif ($protocolinfo =~ /_pdl-datastream/) { + $protocol = "socket"; + } elsif ($protocolinfo =~ /_printer/) { + $protocol = "lpd"; + } elsif ($protocolinfo =~ /_ipp/) { + $protocol = "ipp"; + } + } elsif ($line =~ /^\s*hostname\s*=\s*\[([^\]]+)\]\s*$/) { + $host = $1; + $host =~ s/\.local\.?$//; + } elsif ($line =~ /^\s*address\s*=\s*\[([^\]]+)\]\s*$/) { + $ip = $1; + if ($protocol eq "computer") { + push (@ipblacklist, $ip); + $protocol = ""; + } + } elsif ($line =~ /^\s*port\s*=\s*\[([^\]]+)\]\s*$/) { + $port = $1; + } elsif ($line =~ /^\s*txt\s*=\s*\[(.+)\]\s*$/) { + my $info = $1; + if ($protocol) { + my ($ty, $product, $pdls, $usb_MFG, $usb_MDL, $usb_DES, $usb_CMD) = + ("", "", "", "", "", "", ""); + while ($info =~ s/^\s*\"([^\"]+)\"\s*//) { + my $infoitem = $1; + if ($infoitem =~ /^([^=]*)=(.*)$/) { + my $field = $1; + my $content = $2; + if ($field eq "ty") { + $ty = $content; + } elsif ($field eq "product") { + $product = $content; + $product =~ s/^\((.*)\)$/$1/; + } elsif ($field eq "usb_MFG") { + $usb_MFG = $content; + } elsif ($field eq "usb_MDL") { + $usb_MDL = $content; + } elsif ($field eq "usb_DES") { + $usb_DES = $content; + } elsif ($field eq "usb_CMD") { + $usb_CMD = $content; + } elsif ($field eq "rp") { + $uriext = $content; + } elsif ($field eq "pdl") { + while ($content =~ s/^\s*([^\,]+?)\s*\,\s*//) { + my $i = $1; + if ($i =~ m!\b(postscript|ps)\b!i) { + $pdls .= "POSTSCRIPT,"; + } elsif ($i =~ m!\b(pdf)\b!i) { + $pdls .= "PDF,"; + } elsif ($i =~ m!\b(pcl6|pclxl|pxl)\b!i) { + $pdls .= "PCLXL,"; + } elsif ($i =~ m!\b(pcl[345][ce]?|pcl)\b!i) { + $pdls .= "PCL,"; + } + } + $pdls =~ s/\,$//; + } + } + } + $usb_MDL ||= $ty; + $usb_DES ||= $product; + if ($usb_MFG) { + $make = $usb_MFG; + } elsif ($usb_DES =~ /^KONICA\s+MINOLTA\b/i) { + $make = "KONICA MINOLTA"; + } elsif ($usb_DES) { + $usb_DES =~ /^\s*(\S*)\b/; + $make = $1; + } + $model = $usb_MDL; + if (!$model) { + $usb_DES =~ /^\s*\S*\s*(.*)$/; + $model = $1; + } + $usb_CMD ||= $pdls; + my $extra; + if ($protocol eq "socket") { + $uri = "socket://$ip:$port"; + $extra = "Port $port"; + } elsif ($protocol eq "lpd") { + $uri = "lpd://$ip" . ($uriext ? "/$uriext" : ""); + $extra = ($uriext ? "Queue: $uriext" : "Default queue"); + } elsif ($protocol eq "ipp") { + $uri = "ipp://$ip:$port" . ($uriext ? "/$uriext" : ""); + $extra = ($uriext ? "Queue: $uriext" : "Default queue"); + } + if ($make && $model) { + $make =~ s/Hewlett.?Packard/HP/i; + $make =~ s/Lexmark.?International/Lexmark/i; + $model =~ s/Hewlett.?Packard/HP/i; + $model =~ s/Lexmark.?International/Lexmark/i; + while ($model =~ s/^\s*$make\s*//i) {}; + $makemodel = "$make $model"; + } elsif ($usb_DES) { + $makemodel = $usb_DES; + } else { + $makemodel = "Unknown"; + } + $deviceid = ($usb_MFG ? "MFG:$usb_MFG;" : "") . + ($usb_MDL ? "MDL:$usb_MDL;" : "") . + ($usb_DES ? "DES:$usb_DES;" : "") . + ($usb_CMD ? "CMD:$usb_CMD;" : ""); + $deviceid .= "CLS:PRINTER;" if $deviceid; + $output->{$ip}{$protocol}{$extra} = + "network $uri \"$makemodel\" \"$makemodel $ip ($extra)\" \"$deviceid\"\n"; + ($interface, $nettype, $ip, $host, $make, $model, $description, $cmd, $makemodel, $deviceid, $protocol, $port, $uriext, $uri) = + ("", "", "", "", "", "", "", "", "", "", "", "", "", ""); + } + } +} + +foreach my $ip (keys(%{$output})) { + next if member($ip, @ipblacklist); + if ($output->{$ip}{"socket"}) { + foreach my $extra (keys(%{$output->{$ip}{"socket"}})) { + if (keys(%{$output->{$ip}{"socket"}}) = 1) { + $output->{$ip}{"socket"}{$extra} =~ + s/^(\s*\S*\s*\S*\s*\"[^\"]*\"\s*\"[^\"\(]*?)\s*\([^\)]*\)\s*(\"\s*.*)$/$1$2/; + } + print $output->{$ip}{"socket"}{$extra}; + } + } elsif ($output->{$ip}{"lpd"}) { + foreach my $extra (keys(%{$output->{$ip}{"lpd"}})) { + if (keys(%{$output->{$ip}{"lpd"}}) = 1) { + $output->{$ip}{"lpd"}{$extra} =~ + s/^(\s*\S*\s*\S*\s*\"[^\"]*\"\s*\"[^\"\(]*?)\s*\([^\)]*\)\s*(\"\s*.*)$/$1$2/; + } + print $output->{$ip}{"lpd"}{$extra}; + } + } elsif ($output->{$ip}{"ipp"}) { + foreach my $extra (keys(%{$output->{$ip}{"ipp"}})) { + if (keys(%{$output->{$ip}{"ipp"}}) == 1) { + $output->{$ip}{"ipp"}{$extra} =~ + s/^(\s*\S*\s*\S*\s*\"[^\"]*\"\s*\"[^\"]*?)\s*\([^\)]*\)\s*(\"\s*.*)$/$1$2/; + } + print $output->{$ip}{"ipp"}{$extra}; + } + } +} + +exit 0; + +# member( $a, @b ) returns 1 if $a is in @b, 0 otherwise. +sub member { my $e = shift; foreach (@_) { $e eq $_ and return 1 } 0 };