summaryrefslogtreecommitdiffstats
path: root/perl-install/printer/detect.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/printer/detect.pm')
-rw-r--r--perl-install/printer/detect.pm249
1 files changed, 182 insertions, 67 deletions
diff --git a/perl-install/printer/detect.pm b/perl-install/printer/detect.pm
index 71adef0cf..fcb8316dd 100644
--- a/perl-install/printer/detect.pm
+++ b/perl-install/printer/detect.pm
@@ -8,17 +8,23 @@ use printer::data;
sub local_detect() {
modules::get_probeall("usb-interface") and eval { modules::load($usbprintermodule) };
- eval { modules::unload(qw(lp parport_pc parport)) }; #- on kernel 2.4 parport has to be unloaded to probe again
- eval { modules::load(qw(parport_pc lp)) }; #- take care as not available on 2.4 kernel (silent error).
- whatPrinter();
+ # Reload parallel port modules only when we were not called by
+ # automatic setup of print queues, to avoid recursive calls
+ if ($::autoqueue) {
+ whatUsbport();
+ } else {
+ eval { modules::unload(qw(lp parport_pc ppdev parport)) }; #- on kernel 2.4 parport has to be unloaded to probe again
+ eval { modules::load(qw(ppdev parport_pc lp)) }; #- take care as not available on 2.4 kernel (silent error).
+ whatPrinter();
+ }
}
-sub net_detect() { whatNetPrinter(1, 0) }
+sub net_detect { whatNetPrinter(1, 0, @_) }
-sub net_smb_detect() { whatNetPrinter(0, 1) }
+sub net_smb_detect { whatNetPrinter(0, 1, @_) }
-sub detect() {
- local_detect(), whatNetPrinter(1, 1);
+sub detect {
+ local_detect(), whatNetPrinter(1, 1, @_);
}
@@ -34,26 +40,32 @@ sub whatPrinter() {
sub whatParport() {
my @res;
- foreach (0..3) {
+ my $i = 0;
+ foreach (sort { $a =~ /(\d+)/; my $m = $1; $b =~ /(\d+)/; my $n = $1; $m <=> $n } `ls -1d /proc/parport/[0-9]* /proc/sys/dev/parport/parport[0-9]* 2>/dev/null`) {
+ chomp;
my $elem = {};
my $F;
- open $F, "/proc/parport/$_/autoprobe" or open $F, "/proc/sys/dev/parport/parport$_/autoprobe" or next;
+ open $F, "$_/autoprobe" or next;
{
local $_;
my $itemfound = 0;
- while (<$F>) {
+ while (<$F>) {
+ chomp;
if (/(.*):(.*);/) { #-#
$elem->{$1} = $2;
$elem->{$1} =~ s/Hewlett[-\s_]Packard/HP/;
$elem->{$1} =~ s/HEWLETT[-\s_]PACKARD/HP/;
$itemfound = 1;
+ # Add IEEE-1284 device ID string
+ $elem->{IEEE1284} .= $_;
}
}
# Some parallel printers miss the "CLASS" field
$elem->{CLASS} = 'PRINTER'
if $itemfound && !defined($elem->{CLASS});
}
- push @res, { port => "/dev/lp$_", val => $elem };
+ push @res, { port => "/dev/lp$i", val => $elem };
+ $i ++;
}
@res;
}
@@ -99,6 +111,10 @@ sub whatUsbport() {
next;
};
close $PORT;
+ # Cut resulting string to its real length
+ my $length = ord(substr($idstr, 1, 1)) +
+ (ord(substr($idstr, 0, 1)) << 8);
+ $idstr = substr($idstr, 2, $length-2);
# Remove non-printable characters
$idstr =~ tr/[\x00-\x1f]/./;
# If we do not find any item in the ID string, we try to read
@@ -108,6 +124,9 @@ sub whatUsbport() {
my ($manufacturer, $model, $serialnumber, $description, $commandset) =
("", "", "", "", "");
my ($sku);
+ if ($idstr =~ /CLS:([^;]+);/ || $idstr =~ /CLASS:([^;]+);/) {
+ $itemfound = 1;
+ }
if ($idstr =~ /MFG:([^;]+);/ || $idstr =~ /MANUFACTURER:([^;]+);/) {
$manufacturer = $1;
$manufacturer =~ s/Hewlett[-\s_]Packard/HP/;
@@ -141,12 +160,12 @@ sub whatUsbport() {
$itemfound = 1;
}
# Nothing found? Try again if not in the third attempt,
- # in the third attempt always accept.
- next if !$itemfound && $j < 3;
+ # after the third attempt give up
+ next if !$itemfound;
# Was there a manufacturer and a model in the string?
if ($manufacturer eq "" || $model eq "") {
$manufacturer = "";
- $model = N("Unknown Model");
+ $model = N("Unknown model");
}
# No description field? Make one out of manufacturer and model.
if ($description eq "") {
@@ -160,7 +179,8 @@ sub whatUsbport() {
DESCRIPTION => $description,
SERIALNUMBER => $serialnumber,
'COMMAND SET' => $commandset,
- SKU => $sku
+ SKU => $sku,
+ IEEE1284 => $idstr,
} };
last;
}
@@ -169,10 +189,14 @@ sub whatUsbport() {
}
sub whatNetPrinter {
- my ($network, $smb) = @_;
+ my ($network, $smb, $timeout) = @_;
my (@res);
+ # Set timeouts for "nmap"
+ $timeout = 4000 if !$timeout;
+ my $irtimeout = $timeout / 2;
+
# Which ports should be scanned?
my @portstoscan;
push @portstoscan, "139" if $smb;
@@ -180,12 +204,13 @@ sub whatNetPrinter {
return () if $#portstoscan < 0;
my $portlist = join ",", @portstoscan;
-
+
# Which hosts should be scanned?
- # (Applying nmap to a whole network is very time-consuming, because nmap
- # waits for a certain timeout period on non-existing hosts, so we get a
- # lists of existing hosts by pinging the broadcast addresses for existing
- # hosts and then scanning only them, which is much faster)
+ # (Applying nmap to a whole network is very time-consuming,
+ # because nmap waits for a certain timeout period on non-existing
+ # hosts, so we get a lists of existing hosts by pinging the
+ # broadcast addresses for existing hosts and then scanning only
+ # them, which is much faster)
my @hostips = getIPsInLocalNetworks();
return () if $#hostips < 0;
my $hostlist = join " ", @hostips;
@@ -194,25 +219,36 @@ sub whatNetPrinter {
# delays caused by machines blocking their ports with a firewall
local *F;
open F, ($::testing ? "" : "chroot $::prefix/ ") .
- qq(/bin/sh -c "export LC_ALL=C; nmap -r -P0 --host_timeout 400 --initial_rtt_timeout 200 -p $portlist $hostlist" |)
+ qq(/bin/sh -c "export LC_ALL=C; nmap -r -P0 --host_timeout $timeout --initial_rtt_timeout $irtimeout -p $portlist $hostlist" 2> /dev/null |)
or return @res;
- my ($host, $ip, $port, $modelinfo) = ("", "", "", "");
+ my ($host, $ip, $port, $modelinfo, $namechecked) = ("", "", "", "", 0);
while (my $line = <F>) {
chomp $line;
# head line of the report of a host with the ports in question open
- #if ($line =~ m/^\s*Interesting\s+ports\s+on\s+(\S*)\s*\(([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\)\s*:\s*$/i) {
- if ($line =~ m/^\s*Interesting\s+ports\s+on\s+(\S*)\s*\((\S+)\)\s*:\s*$/i) {
+ if (($line =~ m/^\s*Interesting\s+ports\s+on\s+(\S*)\s*\((\S+)\)\s*:\s*$/i) ||
+ ($line =~ m/^\s*Interesting\s+ports\s+on\s+(\S+)\s*:\s*$/i)) {
($host, $ip) = ($1, $2);
+ $ip = $host if !$ip;
$host = $ip if $host eq "";
$port = "";
+ $namechecked = 0;
undef $modelinfo;
} elsif ($line =~ m!^\s*(\d+)/\S+\s+open\s+!i) {
next if $ip eq "";
$port = $1;
-
+
+ # Check integrity of the host name (work around DNS problems
+ # by using IP if host name is broken)
+ if (!$namechecked && ($host ne $ip)) {
+ $namechecked = 1; # Do not check more than once
+ my $packedip = gethostbyname("$host");
+ my ($a,$b,$c,$d) = unpack('C4',$packedip);
+ my $ipfromdns = sprintf("%d.%d.%d.%d", $a, $b, $c, $d);
+ $host = $ip if $ip ne $ipfromdns;
+ }
# Now we have all info for one printer
# Store this auto-detection result in the data structure
@@ -224,7 +260,7 @@ sub whatNetPrinter {
foreach my $share (@shares) {
push @res, { port => "smb://$host/$share->{name}",
val => { CLASS => 'PRINTER',
- MODEL => N("Unknown Model"),
+ MODEL => N("Unknown model"),
MANUFACTURER => "",
DESCRIPTION => $share->{description},
SERIALNUMBER => ""
@@ -260,7 +296,7 @@ sub getNetworkInterfaces() {
local *IFCONFIG_OUT;
open IFCONFIG_OUT, ($::testing ? "" : "chroot $::prefix/ ") .
- '/bin/sh -c "export LC_ALL=C; ifconfig" |' or return ();
+ '/bin/sh -c "export LC_ALL=C; ifconfig" 2> /dev/null |' or return ();
while (my $readline = <IFCONFIG_OUT>) {
# New entry ...
if ($readline =~ /^(\S+)\s/) {
@@ -291,7 +327,7 @@ sub getIPsOfLocalMachine() {
local *IFCONFIG_OUT;
open IFCONFIG_OUT, ($::testing ? "" : "chroot $::prefix/ ") .
- '/bin/sh -c "export LC_ALL=C; ifconfig" |' or return ();
+ '/bin/sh -c "export LC_ALL=C; ifconfig" 2> /dev/null |' or return ();
while (my $readline = <IFCONFIG_OUT>) {
# New entry ...
if ($readline =~ /^(\S+)\s/) {
@@ -328,57 +364,90 @@ sub getIPsInLocalNetworks() {
# Read the output of "ifconfig" to determine the broadcast addresses of
# the local networks
my $dev_is_localnet = 0;
- my @local_bcasts;
- my $current_bcast = "";
-
+ my $local_nets = {};
+ my $dev;
local *IFCONFIG_OUT;
open IFCONFIG_OUT, ($::testing ? "" : "chroot $::prefix/ ") .
- '/bin/sh -c "export LC_ALL=C; ifconfig" |' or return ();
+ '/bin/sh -c "export LC_ALL=C; ifconfig" 2> /dev/null |' or return ();
while (my $readline = <IFCONFIG_OUT>) {
# New entry ...
if ($readline =~ /^(\S+)\s/) {
- my $dev = $1;
+ $dev = $1;
# ... for a local network (eth = ethernet,
# vmnet = VMWare,
# ethernet card connected to ISP excluded)?
$dev_is_localnet = $dev =~ /^eth/ || $dev =~ /^vmnet/;
- # delete previous address
- $current_bcast = "";
}
- # Are we in the important line now?
- if ($readline =~ /\sBcast:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
- # Rip out the broadcast IP address
- $current_bcast = $1;
-
- # Are we in an entry for a local network?
- if ($dev_is_localnet == 1) {
- # Store current IP address
- push @local_bcasts, $current_bcast;
+ if ($dev_is_localnet) {
+ # Are we in the important line now?
+ if ($readline =~ /\saddr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+ # Rip out the broadcast IP address
+ $local_nets->{$dev}{ip} = $1;
+ }
+ if ($readline =~ /\sBcast:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+ # Rip out the broadcast IP address
+ $local_nets->{$dev}{bcast} = $1;
+ }
+ if ($readline =~ /\sMask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s/) {
+ # Rip out the broadcast IP address
+ $local_nets->{$dev}{mask} = $1;
}
}
}
close(IFCONFIG_OUT);
+ # Now find all addresses in the local networks which we will investigate
my @addresses;
- # Now ping all broadcast addresses and additionally "nmblookup" the
- # networks (to find Windows servers which do not answer to ping)
- foreach my $bcast (@local_bcasts) {
- local *F;
- open F, ($::testing ? "" : "chroot $::prefix/ ") .
- qq(/bin/sh -c "export LC_ALL=C; ping -w 1 -b -n $bcast | cut -f 4 -d ' ' | sed s/:// | egrep '^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+' | uniq | sort" |)
- or next;
- local $_;
- while (<F>) { chomp; push @addresses, $_ }
- close F;
- if (-x "/usr/bin/nmblookup") {
+ foreach $dev (keys %{$local_nets}) {
+ my $ip = $local_nets->{$dev}{ip};
+ my $bcast = $local_nets->{$dev}{bcast};
+ my $mask = $local_nets->{$dev}{mask};
+ if ($mask =~ /255.255.255.(\d+)/) {
+ # Small network, never more than 255 boxes, so we return
+ # all addresses belonging to this network, without pinging
+ my $lastnumber = $1;
+ my $masknumber;
+ if ($lastnumber < 128) {
+ $masknumber = 24;
+ } elsif ($lastnumber < 192) {
+ $masknumber = 25;
+ } elsif ($lastnumber < 224) {
+ $masknumber = 26;
+ } elsif ($lastnumber < 240) {
+ $masknumber = 27;
+ } elsif ($lastnumber < 248) {
+ $masknumber = 28;
+ } elsif ($lastnumber < 252) {
+ $masknumber = 29;
+ } elsif ($lastnumber < 254) {
+ $masknumber = 30;
+ } elsif ($lastnumber < 255) {
+ $masknumber = 31;
+ } else {
+ $masknumber = 32;
+ }
+ push @addresses, "$ip/$masknumber";
+ } else {
+ # Big network, probably more than 255 boxes, so ping the
+ # broadcast address and additionally "nmblookup" the
+ # networks (to find Windows servers which do not answer to ping)
local *F;
open F, ($::testing ? "" : "chroot $::prefix/ ") .
- qq(/bin/sh -c "export LC_ALL=C; nmblookup -B $bcast \\* | cut -f 1 -d ' ' | egrep '^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+' | uniq | sort" |)
+ qq(/bin/sh -c "export LC_ALL=C; ping -w 1 -b -n $bcast 2> /dev/null | cut -f 4 -d ' ' | sed s/:// | egrep '^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+' | uniq | sort" |)
or next;
local $_;
- while (<F>) {
- chomp;
- push @addresses, $_ if !(member($_,@addresses));
+ while (<F>) { chomp; push @addresses, $_ }
+ close F;
+ if (-x "/usr/bin/nmblookup") {
+ local *F;
+ open F, ($::testing ? "" : "chroot $::prefix/ ") .
+ qq(/bin/sh -c "export LC_ALL=C; nmblookup -B $bcast \\* 2> /dev/null | cut -f 1 -d ' ' | egrep '^[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+' | uniq | sort" |)
+ or next;
+ local $_;
+ while (<F>) {
+ chomp;
+ push @addresses, $_ if !(member($_,@addresses));
+ }
}
}
}
@@ -392,7 +461,7 @@ sub getSMBPrinterShares {
# SMB request to auto-detect shares
local *F;
open F, ($::testing ? "" : "chroot $::prefix/ ") .
- qq(/bin/sh -c "export LC_ALL=C; smbclient -N -L $host" |) or return ();
+ qq(/bin/sh -c "export LC_ALL=C; smbclient -N -L $host" 2> /dev/null |) or return ();
my $insharelist = 0;
my @shares;
while (my $l = <F>) {
@@ -424,9 +493,9 @@ sub getSNMPModel {
# SNMP request to auto-detect model
local *F;
open F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
- qq(/bin/sh -c "scli -v 1 -c 'show printer info' $host" |) or
+ qq(/bin/sh -c "scli -v 1 -c 'show printer info' $host" 2> /dev/null |) or
return { CLASS => 'PRINTER',
- MODEL => N("Unknown Model"),
+ MODEL => N("Unknown model"),
MANUFACTURER => "",
DESCRIPTION => "",
SERIALNUMBER => ""
@@ -453,7 +522,43 @@ sub getSNMPModel {
# Was there a manufacturer and a model in the output?
# If not, get them from the description
if ($manufacturer eq "" || $model eq "") {
- if ($description =~ /^\s*(\S*)\s+(\S.*)$/) {
+ # Replace bad description
+ if ((length($description) < 5) &&
+ (length($description) >= 5)) {
+ $description = $model;
+ }
+ # Guess manufacturer by model name
+ if ($description =~
+ /^\s*(DeskJet|LaserJet|OfficeJet|PSC|PhotoSmart)\b/i) {
+ # HP printer
+ $manufacturer = "HP";
+ $model = $description;
+ } elsif ($description =~
+ /^\s*(Stylus|EPL|AcuLaser)\b/i) {
+ # Epson printer
+ $manufacturer = "Epson";
+ $model = $description;
+ } elsif ($description =~
+ /^\s*(Aficio)\b/i) {
+ # Ricoh printer
+ $manufacturer = "Ricoh";
+ $model = $description;
+ } elsif ($description =~
+ /^\s*(Optra|Color\s+JetPrinter)\b/i) {
+ # Lexmark printer
+ $manufacturer = "Lexmark";
+ $model = $description;
+ } elsif ($description =~
+ /^\s*(imageRunner|Pixma|Pixus|BJC|LBP)\b/i) {
+ # Canon printer
+ $manufacturer = "Canon";
+ $model = $description;
+ } elsif ($description =~
+ /^\s*(Phaser|DocuPrint|(Work|Document)\s*(Home|)Centre)\b/i) {
+ # Xerox printer
+ $manufacturer = "Xerox";
+ $model = $description;
+ } elsif ($description =~ /^\s*(\S*)\s+(\S.*)$/) {
$manufacturer = $1 if $manufacturer eq "";
$model = $2 if $model eq "";
}
@@ -463,7 +568,7 @@ sub getSNMPModel {
}
# We couldn't determine a model
- $model = N("Unknown Model") if $model eq "";
+ $model = N("Unknown model") if $model eq "";
# Remove trailing spaces
$manufacturer =~ s/(\S+)\s+$/$1/;
@@ -485,7 +590,7 @@ sub network_running() {
# If the network is not running return 0, otherwise 1.
local *F;
open F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
- '/bin/sh -c "export LC_ALL=C; /sbin/ifconfig" |' or
+ '/bin/sh -c "export LC_ALL=C; /sbin/ifconfig" 2> /dev/null |' or
die 'Could not run "ifconfig"!';
while (my $line = <F>) {
if ($line !~ /^lo\s+/ && # The loopback device can have been
@@ -506,8 +611,18 @@ sub parport_addr {
$device =~ m!^/dev/lp(\d+)$! or
$device =~ m!^/dev/printers/(\d+)$!;
my $portnumber = $1;
+ my $i = 0;
+ my $parportdir;
+ foreach (sort { $a =~ /(\d+)/; my $m = $1; $b =~ /(\d+)/; my $n = $1; $m <=> $n } `ls -1d /proc/parport/[0-9]* /proc/sys/dev/parport/parport[0-9]* 2>/dev/null`) {
+ chomp;
+ if ($i == $portnumber) {
+ $parportdir = $_;
+ last;
+ }
+ $i++;
+ }
my $parport_addresses =
- `cat /proc/sys/dev/parport/parport$portnumber/base-addr`;
+ `cat $parportdir/base-addr`;
my $address_arg;
if ($parport_addresses =~ /^\s*(\d+)\s+(\d+)\s*$/) {
$address_arg = sprintf(" -base 0x%x -basehigh 0x%x", $1, $2);