summaryrefslogtreecommitdiffstats
path: root/perl-install/printer/main.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/printer/main.pm')
-rw-r--r--perl-install/printer/main.pm1674
1 files changed, 991 insertions, 683 deletions
diff --git a/perl-install/printer/main.pm b/perl-install/printer/main.pm
index d9f06ddde..31d8981ba 100644
--- a/perl-install/printer/main.pm
+++ b/perl-install/printer/main.pm
@@ -9,28 +9,24 @@ use run_program;
use printer::data;
use printer::services;
use printer::default;
-use printer::gimp;
use printer::cups;
-use printer::office;
use printer::detect;
use handle_configs;
use services;
+use lang;
use vars qw(@ISA @EXPORT);
@ISA = qw(Exporter);
@EXPORT = qw(%printer_type %printer_type_inv);
-#-Did we already read the subroutines of /usr/sbin/ptal-init?
-my $ptalinitread = 0;
-
our %printer_type = (
N("Local printer") => "LOCAL",
N("Remote printer") => "REMOTE",
N("Printer on remote CUPS server") => "CUPS",
N("Printer on remote lpd server") => "LPD",
N("Network printer (TCP/Socket)") => "SOCKET",
- N("Printer on SMB/Windows 95/98/NT server") => "SMB",
+ N("Printer on SMB/Windows server") => "SMB",
N("Printer on NetWare server") => "NCP",
N("Enter a printer device URI") => "URI",
N("Pipe job into a command") => "POSTPIPE"
@@ -39,6 +35,14 @@ our %printer_type = (
our %printer_type_inv = reverse %printer_type;
our %thedb;
+our %linkedppds;
+
+our $hplipdevicesdb;
+
+# Translation of the "(recommended)" in printer driver entries
+our $recstr = N("recommended");
+our $precstr = "($recstr)";
+our $sprecstr = quotemeta($precstr);
#------------------------------------------------------------------------------
@@ -56,9 +60,9 @@ sub spooler() {
# PDQ is not officially supported any more since version 9.1, so
# show it only in the spooler menu when it was manually installed.
- return map { $spoolers{$_}{long_name} } qw(cups),
+ return map { $spoolers{$_}{long_name} } ('cups', 'rcups' ,
if_(files_exist(qw(/usr/bin/pdq)), 'pdq'),
- if_(files_exist(qw(/usr/lib/filters/lpf /usr/sbin/lpd)), 'lprng');
+ if_(files_exist("/usr/$lib/filters/lpf", "/usr/sbin/lpd"), 'lprng'));
}
sub printer_type($) {
@@ -68,14 +72,15 @@ sub printer_type($) {
/lpd/ and return @printer_type_inv{qw(LOCAL LPD SOCKET SMB NCP), if_($printer->{expert}, qw(POSTPIPE URI))};
/lprng/ and return @printer_type_inv{qw(LOCAL LPD SOCKET SMB NCP), if_($printer->{expert}, qw(POSTPIPE URI))};
/pdq/ and return @printer_type_inv{qw(LOCAL LPD SOCKET), if_($printer->{expert}, qw(URI))};
+ /rcups/ and return ();
}
}
sub SIGHUP_daemon {
my ($service) = @_;
- if ($service eq "cupsd") { $service = "cups" };
- # PDQ has no daemon, exit.
- if ($service eq "pdq") { return 1 };
+ if ($service eq "cupsd") { $service = "cups" }
+ # PDQ and remote CUPS have no daemons, exit.
+ if (($service eq "pdq") || ($service eq "rcups")) { return 1 }
# CUPS needs auto-correction for its configuration
run_program::rooted($::prefix, "/usr/sbin/correctcupsconfig") if $service eq "cups";
# Name of the daemon
@@ -125,18 +130,17 @@ sub assure_device_is_available_for_cups {
}
my $maxattempts = 3;
for ($i = 0; $i < $maxattempts; $i++) {
- local *F;
- open F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
- '/bin/sh -c "export LC_ALL=C; /usr/sbin/lpinfo -v" |' or
+ open(my $F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
+ '/bin/sh -c "export LC_ALL=C; /usr/sbin/lpinfo -v" |') or
die 'Could not run "lpinfo"!';
- while (my $line = <F>) {
+ while (my $line = <$F>) {
if ($line =~ /$sdevice/) { # Found a line containing the device
# name, so CUPS knows it.
- close F;
+ close $F;
return 1;
}
}
- close F;
+ close $F;
$result = printer::services::restart("cups");
}
return $result;
@@ -150,15 +154,14 @@ sub spooler_in_security_level {
$sp = $spooler eq "lpr" || $spooler eq "lprng" ? "lpd" : $spooler;
my $file = "$::prefix/etc/security/msec/server.$level";
if (-f $file) {
- local *F;
- open F, "< $file" or return 0;
- while (my $line = <F>) {
+ open(my $F, "< $file") or return 0;
+ while (my $line = <$F>) {
if ($line =~ /^\s*$sp\s*$/) {
- close F;
+ close $F;
return 1;
}
}
- close F;
+ close $F;
}
return 0;
}
@@ -206,7 +209,7 @@ sub resetinfo($) {
$printer->{QUEUE} = "";
$printer->{OLD_QUEUE} = "";
$printer->{OLD_CHOICE} = "";
- $printer->{ARGS} = "";
+ $printer->{ARGS} = {};
$printer->{DBENTRY} = "";
$printer->{DEFAULT} = "";
$printer->{currentqueue} = {};
@@ -222,24 +225,26 @@ sub read_configured_queues($) {
$printer->{SPOOLER} ||= printer::default::get_spooler();
if (!$printer->{SPOOLER}) {
#- Find the first spooler where there are queues
- foreach my $spooler (qw(cups pdq lprng lpd)) {
+ foreach my $spooler (qw(rcups cups pdq lprng lpd)) {
#- Is the spooler's daemon running?
my $service = $spooler;
if ($service eq "lprng") {
$service = "lpd";
}
- if ($service ne "pdq") {
+ if (($service ne "pdq") && ($service ne "rcups")) {
next unless services::is_service_running($service);
# daemon is running, spooler found
$printer->{SPOOLER} = $spooler;
}
- #- poll queue info
- local *F;
- open F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
- "foomatic-configure -P -q -s $spooler |" or
- die "Could not run foomatic-configure";
- eval join('', <F>);
- close F;
+ #- poll queue info
+ if ($service ne "rcups") {
+ open(my $F, ($::testing ?
+ $::prefix : "chroot $::prefix/ ") .
+ "foomatic-configure -P -q -s $spooler |") or
+ die "Could not run foomatic-configure";
+ eval join('', <$F>);
+ close $F;
+ }
if ($service eq "pdq") {
#- Have we found queues? PDQ has no damon, so we consider
#- it in use when there are defined printer queues
@@ -247,6 +252,17 @@ sub read_configured_queues($) {
$printer->{SPOOLER} = $spooler;
last;
}
+ } elsif ($service eq "rcups") {
+ #- In daemon-less CUPS mode there are no local queues,
+ #- we can only recognize it by a server entry in
+ #- /etc/cups/client.conf
+ my ($daemonless_cups, $remote_cups_server) =
+ printer::main::read_client_conf();
+ if ($daemonless_cups) {
+ $printer->{SPOOLER} = $spooler;
+ $printer->{remote_cups_server} = $remote_cups_server;
+ last;
+ }
} else {
#- For other spoolers we have already found a running
#- daemon when we have arrived here
@@ -254,13 +270,18 @@ sub read_configured_queues($) {
}
}
} else {
- #- Poll the queues of the current default spooler
- local *F;
- open F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
- "foomatic-configure -P -q -s $printer->{SPOOLER} -r |" or
- die "Could not run foomatic-configure";
- eval join('', <F>);
- close F;
+ if ($printer->{SPOOLER} ne "rcups") {
+ #- Poll the queues of the current default spooler
+ open(my $F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
+ "foomatic-configure -P -q -s $printer->{SPOOLER} -r |") or
+ die "Could not run foomatic-configure";
+ eval join('', <$F>);
+ close $F;
+ } else {
+ my ($_daemonless_cups, $remote_cups_server) =
+ printer::main::read_client_conf();
+ $printer->{remote_cups_server} = $remote_cups_server;
+ }
}
$printer->{configured} = {};
my $i;
@@ -285,21 +306,24 @@ sub read_configured_queues($) {
}
# Read out which PPD file was originally used to set up this
# queue
- local *F;
- if (open F, "< $::prefix/etc/cups/ppd/$QUEUES[$i]{queuedata}{queue}.ppd") {
- while (my $line = <F>) {
+ if (open(my $F, "< $::prefix/etc/cups/ppd/$QUEUES[$i]{queuedata}{queue}.ppd")) {
+ while (my $line = <$F>) {
if ($line =~ /^\*%MDKMODELCHOICE:(.+)$/) {
$printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{ppd} = $1;
}
}
- close F;
- }
- # Mark that we have a CUPS queue but do not know the name
- # the PPD file in /usr/share/cups/model
- if (!$printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{ppd}) {
- $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{ppd} = '1';
+ close $F;
+ # Mark that we have a CUPS queue but do not know the
+ # name the PPD file in /usr/share/cups/model
+ $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{ppd} ||= '1';
+ # Mark that our PPD file is not a Foomatic one
+ $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{driver} = "PPD";
+ } else {
+ # We do not have a PPD file for this queue
+ $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{ppd} = undef;
+ # No PPD found? Then we have a raw queue
+ $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{driver} = "raw";
}
- $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{driver} = 'PPD';
$printer->{OLD_QUEUE} = "";
}
$printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{make} ||= "";
@@ -340,6 +364,17 @@ sub make_menuentry {
$connection = N(", USB printer #%s", $number);
} elsif ($connect =~ m!^usb://!) {
$connection = N(", USB printer");
+ } elsif ($connect =~ m!^hp:/(.+?)$!) {
+ my $hplipdevice = $1;
+ if ($hplipdevice =~ m!^par/!) {
+ $connection = N(", HP printer on a parallel port");
+ } elsif ($hplipdevice =~ m!^usb/!) {
+ $connection = N(", HP printer on USB");
+ } elsif ($hplipdevice =~ m!^net/!) {
+ $connection = N(", HP printer on HP JetDirect");
+ } else {
+ $connection = N(", HP printer");
+ }
} elsif ($connect =~ m!^ptal://?(.+?)$!) {
my $ptaldevice = $1;
if ($ptaldevice =~ /^mlc:par:(\d+)$/) {
@@ -356,21 +391,27 @@ sub make_menuentry {
$connection = N(", multi-function device");
}
} elsif ($connect =~ m!^file:(.+)$!) {
- $connection = N(", printing to %s", $1);
+ my $file = $1;
+ $connection = N(", printing to %s", $file);
} elsif ($connect =~ m!^lpd://([^/]+)/([^/]+)/?$!) {
- $connection = N(" on LPD server \"%s\", printer \"%s\"", $1, $2);
+ my ($server, $printer) = ($1, $2);
+ $connection = N(" on LPD server \"%s\", printer \"%s\"", $server, $printer);
} elsif ($connect =~ m!^socket://([^/:]+):([^/:]+)/?$!) {
- $connection = N(", TCP/IP host \"%s\", port %s", $1, $2);
+ my ($host, $port) = ($1, $2);
+ $connection = N(", TCP/IP host \"%s\", port %s", $host, $port);
} elsif ($connect =~ m!^smb://([^/\@]+)/([^/\@]+)/?$! ||
$connect =~ m!^smb://.*/([^/\@]+)/([^/\@]+)/?$! ||
$connect =~ m!^smb://.*\@([^/\@]+)/([^/\@]+)/?$!) {
- $connection = N(" on SMB/Windows server \"%s\", share \"%s\"", $1, $2);
+ my ($server, $share) = ($1, $2);
+ $connection = N(" on SMB/Windows server \"%s\", share \"%s\"", $server, $share);
} elsif ($connect =~ m!^ncp://([^/\@]+)/([^/\@]+)/?$! ||
$connect =~ m!^ncp://.*/([^/\@]+)/([^/\@]+)/?$! ||
$connect =~ m!^ncp://.*\@([^/\@]+)/([^/\@]+)/?$!) {
- $connection = N(" on Novell server \"%s\", printer \"%s\"", $1, $2);
+ my ($server, $printer) = ($1, $2);
+ $connection = N(" on Novell server \"%s\", printer \"%s\"", $server, $printer);
} elsif ($connect =~ m!^postpipe:(.+)$!) {
- $connection = N(", using command %s", $1);
+ my $command = $1;
+ $connection = N(", using command %s", $command);
} else {
$connection = ($printer->{expert} ? ", URI: $connect" : "");
}
@@ -391,6 +432,17 @@ sub connectionstr {
$connection = N("USB printer #%s", $number);
} elsif ($connect =~ m!^usb://!) {
$connection = N("USB printer");
+ } elsif ($connect =~ m!^hp:/(.+?)$!) {
+ my $hplipdevice = $1;
+ if ($hplipdevice =~ m!^par/!) {
+ $connection = N("HP printer on a parallel port");
+ } elsif ($hplipdevice =~ m!^usb/!) {
+ $connection = N("HP printer on USB");
+ } elsif ($hplipdevice =~ m!^net/!) {
+ $connection = N("HP printer on HP JetDirect");
+ } else {
+ $connection = N("HP printer");
+ }
} elsif ($connect =~ m!^ptal://?(.+?)$!) {
my $ptaldevice = $1;
if ($ptaldevice =~ /^mlc:par:(\d+)$/) {
@@ -407,21 +459,27 @@ sub connectionstr {
$connection = N("Multi-function device");
}
} elsif ($connect =~ m!^file:(.+)$!) {
- $connection = N("Prints into %s", $1);
+ my $file = $1;
+ $connection = N("Prints into %s", $file);
} elsif ($connect =~ m!^lpd://([^/]+)/([^/]+)/?$!) {
- $connection = N("LPD server \"%s\", printer \"%s\"", $1, $2);
+ my ($server, $port) = ($1, $2);
+ $connection = N("LPD server \"%s\", printer \"%s\"", $server, $port);
} elsif ($connect =~ m!^socket://([^/:]+):([^/:]+)/?$!) {
- $connection = N("TCP/IP host \"%s\", port %s", $1, $2);
+ my ($host, $port) = ($1, $2);
+ $connection = N("TCP/IP host \"%s\", port %s", $host, $port);
} elsif ($connect =~ m!^smb://([^/\@]+)/([^/\@]+)/?$! ||
$connect =~ m!^smb://.*/([^/\@]+)/([^/\@]+)/?$! ||
$connect =~ m!^smb://.*\@([^/\@]+)/([^/\@]+)/?$!) {
- $connection = N("SMB/Windows server \"%s\", share \"%s\"", $1, $2);
+ my ($server, $share) = ($1, $2);
+ $connection = N("SMB/Windows server \"%s\", share \"%s\"", $server, $share);
} elsif ($connect =~ m!^ncp://([^/\@]+)/([^/\@]+)/?$! ||
$connect =~ m!^ncp://.*/([^/\@]+)/([^/\@]+)/?$! ||
$connect =~ m!^ncp://.*\@([^/\@]+)/([^/\@]+)/?$!) {
- $connection = N("Novell server \"%s\", printer \"%s\"", $1, $2);
+ my ($server, $share) = ($1, $2);
+ $connection = N("Novell server \"%s\", printer \"%s\"", $server, $share);
} elsif ($connect =~ m!^postpipe:(.+)$!) {
- $connection = N("Uses command %s", $1);
+ my $command = $1;
+ $connection = N("Uses command %s", $command);
} else {
$connection = N("URI: %s", $connect);
}
@@ -430,22 +488,36 @@ sub connectionstr {
sub read_printer_db {
- my ($printer, $spooler) = @_;
+ my ($printer, $spooler, $newppd) = @_;
+
+ # If a $newppd is supplied, we return the key of the DB entry which
+ # is for this file. This way we can pre-select a freshly added PPD in
+ # the model/driver list.
- local *DBPATH; #- don't have to do close ... and don't modify globals at least
- # Generate the Foomatic printer/driver overview, read it from the
- # appropriate file when it is already generated
- open DBPATH, ($::testing ? $::prefix : "chroot $::prefix/ ") . #-#
- "foomatic-configure -O -q |" or
+ # No local queues available in daemon-less CUPS mode
+ return 1 if $spooler eq "rcups";
+
+ my $DBPATH; #- do not have to do close ... and do not modify globals at least
+ # Generate the Foomatic printer/driver overview
+ open($DBPATH, ($::testing ? $::prefix : "chroot $::prefix/ ") . #-#
+ "foomatic-configure -O -q |") or
die "Could not run foomatic-configure";
+ %linkedppds = ();
my $entry = {};
+ @{$entry->{drivers}} = ();
my $inentry = 0;
my $indrivers = 0;
+ my $inppds = 0;
+ my $inppd = 0;
my $inautodetect = 0;
my $autodetecttype = "";
+ my $ppds = {};
+ my $ppddriver = "";
+ my $ppdfile = "";
+ my $ppdentry = "";
local $_;
- while (<DBPATH>) {
+ while (<$DBPATH>) {
chomp;
if ($inentry) {
# We are inside a printer entry
@@ -457,6 +529,31 @@ sub read_printer_db {
} elsif (m!^\s*<driver>(.+)</driver>\s*$!) {
push @{$entry->{drivers}}, $1;
}
+ } elsif ($inppds) {
+ # We are inside the ppds block of a printers entry
+ if ($inppd) {
+ # We are inside a PPD entry in the ppds block
+ if (m!^\s*</ppd>\s*$!) {
+ # End of ppds block
+ $inppd = 0;
+ if ($ppddriver && $ppdfile) {
+ $ppds->{$ppddriver} = $ppdfile;
+ }
+ $ppddriver = "";
+ $ppdfile = "";
+ } elsif (m!^\s*<driver>(.+)</driver>\s*$!) {
+ $ppddriver = $1;
+ } elsif (m!^\s*<ppdfile>(.+)</ppdfile>\s*$!) {
+ $ppdfile = $1;
+ }
+ } else {
+ if (m!^\s*</ppds>\s*$!) {
+ # End of ppds block
+ $inppds = 0;
+ } elsif (m!^\s*<ppd>\s*$!) {
+ $inppd = 1;
+ }
+ }
} elsif ($inautodetect) {
# We are inside the autodetect block of a printers entry
# All entries inside this block will be ignored
@@ -513,13 +610,20 @@ sub read_printer_db {
$driverstr = "GhostScript + $driver";
}
if ($driver eq $entry->{defaultdriver}) {
- $driverstr .= " (recommended)";
+ $driverstr .= " $precstr";
}
$entry->{ENTRY} = "$entry->{make}|$entry->{model}|$driverstr";
$entry->{ENTRY} =~ s/^CITOH/C.ITOH/i;
$entry->{ENTRY} =~
s/^KYOCERA[\s\-]*MITA/KYOCERA/i;
$entry->{driver} = $driver;
+ if (defined($ppds->{$driver})) {
+ $entry->{ppd} = $ppds->{$driver};
+ $ppds->{$driver} =~ m!([^/]+)$!;
+ push(@{$linkedppds{$1}}, $entry->{ENTRY});
+ } else {
+ undef $entry->{ppd};
+ }
# Duplicate contents of $entry because it is multiply entered to the database
map { $thedb{$entry->{ENTRY}}{$_} = $entry->{$_} } keys %$entry;
}
@@ -532,11 +636,21 @@ sub read_printer_db {
$entry->{ENTRY} =~
s/^KYOCERA[\s\-]*MITA/KYOCERA/i;
if ($entry->{defaultdriver}) {
- $entry->{driver} = $entry->{defaultdriver};
+ my $driver = $entry->{defaultdriver};
+ $entry->{driver} = $driver;
+ if (defined($ppds->{$driver})) {
+ $entry->{ppd} = $ppds->{$driver};
+ $ppds->{$driver} =~ m!([^/]+)$!;
+ push(@{$linkedppds{$1}}, $entry->{ENTRY});
+ } else {
+ undef $entry->{ppd};
+ }
map { $thedb{$entry->{ENTRY}}{$_} = $entry->{$_} } keys %$entry;
}
}
$entry = {};
+ @{$entry->{drivers}} = ();
+ $ppds = {};
} elsif (m!^\s*<id>\s*([^\s<>]+)\s*</id>\s*$!) {
# Foomatic printer ID
$entry->{printer} = $1;
@@ -552,7 +666,9 @@ sub read_printer_db {
} elsif (m!^\s*<drivers>\s*$!) {
# Drivers block
$indrivers = 1;
- @{$entry->{drivers}} = ();
+ } elsif (m!^\s*<ppds>\s*$!) {
+ # PPDs block
+ $inppds = 1;
} elsif (m!^\s*<autodetect>\s*$!) {
# Autodetect block
$inautodetect = 1;
@@ -565,7 +681,7 @@ sub read_printer_db {
}
}
}
- close DBPATH;
+ close $DBPATH;
# Add raw queue
$entry->{ENTRY} = N("Raw printer (No driver)");
@@ -576,7 +692,7 @@ sub read_printer_db {
#- Load CUPS driver database if CUPS is used as spooler
if ($spooler && $spooler eq "cups") {
- poll_ppd_base($printer);
+ $ppdentry = poll_ppd_base($printer, $newppd);
}
#my @entries_db_short = sort keys %printer::thedb;
@@ -585,24 +701,25 @@ sub read_printer_db {
#@entry_db_description = keys %descr_to_db;
#db_to_descr = reverse %descr_to_db;
+ return $ppdentry if $newppd;
+
}
sub read_foomatic_options ($) {
my ($printer) = @_;
# Generate the option data for the chosen printer/driver combo
my $COMBODATA;
- local *F;
- open F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
+ open(my $F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
"foomatic-configure -P -q -p $printer->{currentqueue}{printer}" .
" -d $printer->{currentqueue}{driver}" .
($printer->{OLD_QUEUE} ?
" -s $printer->{SPOOLER} -n $printer->{OLD_QUEUE}" : "") .
($printer->{SPECIAL_OPTIONS} ?
" $printer->{SPECIAL_OPTIONS}" : "")
- . " |" or
+ . " |") or
die "Could not run foomatic-configure";
- eval join('', (<F>));
- close F;
+ eval join('', (<$F>));
+ close $F;
# Return the arguments field
return $COMBODATA->{args};
}
@@ -611,47 +728,77 @@ sub read_ppd_options ($) {
my ($printer) = @_;
# Generate the option data for a given PPD file
my $COMBODATA;
- local *F;
- open F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
+ open(my $F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
"foomatic-configure -P -q" .
- " --ppd /usr/share/cups/model/$printer->{currentqueue}{ppd}" .
+ if_($printer->{currentqueue}{ppd} &&
+ ($printer->{currentqueue}{ppd} ne '1'),
+ " --ppd \'" . ($printer->{currentqueue}{ppd} !~ m!^/! ?
+ "/usr/share/cups/model/" : "") .
+ $printer->{currentqueue}{ppd} . "\'") .
($printer->{OLD_QUEUE} ?
" -s $printer->{SPOOLER} -n $printer->{OLD_QUEUE}" : "") .
($printer->{SPECIAL_OPTIONS} ?
" $printer->{SPECIAL_OPTIONS}" : "")
- . " |" or
+ . " |") or
die "Could not run foomatic-configure";
- eval join('', (<F>));
- close F;
+ eval join('', (<$F>));
+ close $F;
# Return the arguments field
return $COMBODATA->{args};
}
-my %sysconfig = getVarsFromSh("$::prefix/etc/sysconfig/printing");
-
sub set_cups_special_options {
- my ($queue) = $_[0];
+ my ($printer, $queue) = @_;
# Set some special CUPS options
- my @lpoptions = chomp_(cat_("$::prefix/etc/cups/lpoptions"));
- # If nothing is already configured, set text file borders of half an inch
- # and decrease the font size a little bit, so nothing of the text gets
- # cut off by unprintable borders.
- if (!any { /$queue.*\s(page-(top|bottom|left|right)|lpi|cpi)=/ } @lpoptions) {
- run_program::rooted($::prefix, "lpoptions",
- "-p", $queue,
- "-o", "page-top=36", "-o", "page-bottom=36",
- "-o", "page-left=36", "-o page-right=36",
- "-o", "cpi=12", "-o", "lpi=7", "-o", "wrap");
+ my @lpoptions = cat_("$::prefix/etc/cups/lpoptions");
+ # If nothing is already configured, set text file borders of half
+ # an inch so nothing of the text gets cut off by unprintable
+ # borders. Do this only when the driver is not Gutenprint or HPIJS, as
+ # both drivers decent border settings are already done and with
+ # Gutenprint this will even break PostScript printing
+ if ((($queue eq $printer->{currentqueue}{$queue}) &&
+ (($printer->{currentqueue}{driver} =~
+ /(guten.*print|hpijs|hplip)/i) ||
+ ($printer->{currentqueue}{ppd} =~
+ /(guten.*print|hpijs|hplip)/i))) ||
+ ((defined($printer->{configured}{$queue})) &&
+ (($printer->{configured}{$queue}{queuedata}{driver} =~
+ /(guten.*print|hpijs|hplip)/i) ||
+ ($printer->{configured}{$queue}{queuedata}{ppd} =~
+ /(guten.*print|hpijs|hplip)/i))) ||
+ (($printer->{SPOOLER} eq "cups") &&
+ (-r "$::prefix/etc/cups/ppd/$queue.ppd") &&
+ (`egrep -ic '(gutenprint|hpijs|hplip)' $::prefix/etc/cups/ppd/$queue.ppd` > 2))) {
+ # Remove page margin settings
+ foreach (@lpoptions) {
+ s/\s*page-(top|bottom|left|right)=\S+//g if /$queue/;
+ }
+ output("$::prefix/etc/cups/lpoptions", @lpoptions);
+ } else {
+ if (!any { /$queue.*\spage-(top|bottom|left|right)=/ } @lpoptions) {
+ run_program::rooted($::prefix, "lpoptions",
+ "-p", $queue,
+ "-o", "page-top=36", "-o", "page-bottom=36",
+ "-o", "page-left=36", "-o page-right=36");
+ }
}
- # Let images fill the whole page by default
+ # Let images fill the whole page by default and let text be word-wrapped
+ # and printed in a slightly smaller font
if (!any { /$queue.*\s(scaling|natural-scaling|ppi)=/ } @lpoptions) {
run_program::rooted($::prefix, "lpoptions",
"-p", $queue,
"-o", "scaling=100");
}
+ if (!any { /$queue.*\s(cpi|lpi)=/ } @lpoptions) {
+ run_program::rooted($::prefix, "lpoptions",
+ "-p", $queue,
+ "-o", "cpi=12", "-o", "lpi=7", "-o", "wrap");
+ }
return 1;
}
+my %sysconfig = getVarsFromSh("$::prefix/etc/sysconfig/printing");
+
sub set_cups_autoconf {
my ($autoconf) = @_;
$sysconfig{CUPS_CONFIG} = $autoconf ? "automatic" : "manual";
@@ -672,10 +819,54 @@ sub set_usermode {
sub get_usermode() { $sysconfig{USER_MODE} eq 'expert' ? 1 : 0 }
+sub set_auto_admin {
+ my ($printer) = @_;
+ $sysconfig{ENABLE_QUEUES_ON_PRINTER_CONNECTED} =
+ $printer->{enablequeuesonnewprinter} ? "yes" : "no";
+ $sysconfig{AUTO_SETUP_QUEUES_ON_PRINTER_CONNECTED} =
+ $printer->{autoqueuesetuponnewprinter} ? "yes" : "no";
+ $sysconfig{ENABLE_QUEUES_ON_SPOOLER_START} =
+ $printer->{enablequeuesonspoolerstart} ? "yes" : "no";
+ $sysconfig{AUTO_SETUP_QUEUES_ON_PRINTERDRAKE_START} =
+ $printer->{autoqueuesetuponstart} ? "yes" : "no";
+ $sysconfig{AUTO_SETUP_QUEUES_MODE} =
+ $printer->{autoqueuesetupgui} ? "waitforgui" : "nogui";
+ setVarsInSh("$::prefix/etc/sysconfig/printing", \%sysconfig);
+ return 1;
+}
+
+sub get_auto_admin {
+ my ($printer) = @_;
+ $printer->{enablequeuesonnewprinter} =
+ (!defined($sysconfig{ENABLE_QUEUES_ON_PRINTER_CONNECTED}) ||
+ ($sysconfig{ENABLE_QUEUES_ON_PRINTER_CONNECTED} =~ /no/i) ?
+ 0 : 1);
+ $printer->{autoqueuesetuponnewprinter} =
+ (!defined($sysconfig{AUTO_SETUP_QUEUES_ON_PRINTER_CONNECTED}) ||
+ ($sysconfig{AUTO_SETUP_QUEUES_ON_PRINTER_CONNECTED} =~ /yes/i) ?
+ 1 : 0);
+ $printer->{enablequeuesonspoolerstart} =
+ (!defined($sysconfig{ENABLE_QUEUES_ON_SPOOLER_START}) ||
+ ($sysconfig{ENABLE_QUEUES_ON_SPOOLER_START} =~ /no/i) ?
+ 0 : 1);
+ $printer->{autoqueuesetuponstart} =
+ (!defined($sysconfig{AUTO_SETUP_QUEUES_ON_PRINTERDRAKE_START}) ||
+ ($sysconfig{AUTO_SETUP_QUEUES_ON_PRINTERDRAKE_START} =~ /yes/i) ?
+ 1 : 0);
+ $printer->{autoqueuesetupgui} =
+ (!defined($sysconfig{AUTO_SETUP_QUEUES_MODE}) ||
+ ($sysconfig{AUTO_SETUP_QUEUES_MODE} =~ /waitforgui/i) ?
+ 1 : 0);
+}
+
sub set_jap_textmode {
my $textmode = ($_[0] ? 'cjk' : '');
+ # Do not write mime.convs if the file does not exist, as then
+ # CUPS is not installed and the created mime.convs will be broken.
+ # When installing CUPS later it will not work.
+ return 1 if (! -r "$::prefix/etc/cups/mime.convs");
substInFile {
- s!^(\s*text/plain\s+\S+\s+\d+\s+)\S+(\s*$)!$1${textmode}texttops$2!
+ s!^(\s*text/plain\s+\S+\s+\d+\s+)\S+(\s*$)!$1${textmode}texttops$2!;
} "$::prefix/etc/cups/mime.convs";
return 1;
}
@@ -691,15 +882,46 @@ sub get_jap_textmode() {
# Handling of /etc/cups/cupsd.conf
sub read_cupsd_conf() {
- cat_("$::prefix/etc/cups/cupsd.conf");
+ # If /etc/cups/cupsd.conf does not exist a default cupsd.conf will be
+ # put out to avoid writing of a broken cupsd.conf file when we write
+ # it back later.
+ my @cupsd_conf = cat_("$::prefix/etc/cups/cupsd.conf");
+ if (!@cupsd_conf) {
+ @cupsd_conf = map { /\n$/s or "$_\n" } split('\n',
+'LogLevel info
+TempDir /var/spool/cups/tmp
+Port 631
+Browsing On
+BrowseAddress @LOCAL
+BrowseDeny All
+BrowseAllow 127.0.0.1
+BrowseAllow @LOCAL
+BrowseOrder deny,allow
+<Location />
+Order Deny,Allow
+Deny From All
+Allow From 127.0.0.1
+Allow From @LOCAL
+</Location>
+<Location /admin>
+AuthType Basic
+AuthClass System
+Order Deny,Allow
+Deny From All
+Allow From 127.0.0.1
+</Location>
+');
+ }
+ return @cupsd_conf;
}
+
sub write_cupsd_conf {
my (@cupsd_conf) = @_;
-
+ # Do not write cupsd.conf if the file does not exist, as then
+ # CUPS is not installed and the created cupsd.conf will be broken.
+ # When installing CUPS later it will not start.
+ return 1 if (! -r "$::prefix/etc/cups/cupsd.conf");
output("$::prefix/etc/cups/cupsd.conf", @cupsd_conf);
-
- #- restart cups after updating configuration.
- printer::services::restart("cups");
}
sub read_location {
@@ -718,7 +940,7 @@ sub read_location {
my $location_end = -1;
# Go through all the lines, bail out when start and end line found
for (my $i = 0;
- $i <= $#{$cupsd_conf_ptr} and $location_end == -1;
+ $i <= $#{$cupsd_conf_ptr} && $location_end == -1;
$i++) {
if ($cupsd_conf_ptr->[$i] =~ m!^\s*<\s*Location\s+$path\s*>!) {
# Start line of block
@@ -739,7 +961,7 @@ sub read_location {
# "undef"
@result = undef;
}
- return (@result);
+ return @result;
}
sub rip_location {
@@ -761,7 +983,7 @@ sub rip_location {
if (any { m!^\s*<Location\s+$path\s*>! } @$cupsd_conf_ptr) {
# Go through all the lines, bail out when start and end line found
for (my $i = 0;
- $i <= $#{$cupsd_conf_ptr} and $location_end == -1;
+ $i <= $#{$cupsd_conf_ptr} && $location_end == -1;
$i++) {
if ($cupsd_conf_ptr->[$i] =~ m!^\s*<\s*Location\s+$path\s*>!) {
# Start line of block
@@ -784,7 +1006,7 @@ sub rip_location {
@location = ("<Location $path>\n", "</Location>\n");
}
- return ($location_start, @location);
+ return $location_start, @location;
}
sub insert_location {
@@ -912,7 +1134,7 @@ sub networkaddress {
my ($address) = @_;
if ($address =~ /\.255$/) {
- while ($address =~ s/\.255$//) {};
+ while ($address =~ s/\.255$//) {}
$address .= ".*";
}
@@ -1068,7 +1290,7 @@ sub clientnetworks {
$haveallowedhostwithoutbrowseallow ||
$havebrowseallowwithoutallowedhost);
- return ($configunsupported, @sharehosts);
+ return $configunsupported, @sharehosts;
}
sub makesharehostlist {
@@ -1199,7 +1421,7 @@ sub read_cups_config {
my @localips = printer::detect::getIPsOfLocalMachine();
@{$printer->{cupsconfig}{root}{AllowFrom}} =
grep {
- !member($_, @localips)
+ !member($_, @localips);
} @{$printer->{cupsconfig}{root}{AllowFrom}};
# Keyword "Deny from"
@@ -1297,7 +1519,7 @@ sub write_cups_config {
"Allow From " .
join("\nAllow From ",
grep {
- !member($_, @localips)
+ !member($_, @localips);
} @{$printer->{cupsconfig}{clientnetworks}}) .
"\n" : "") .
"</Location>\n";
@@ -1314,7 +1536,7 @@ sub write_cups_config {
@{$printer->{cupsconfig}{clientnetworks}}));
} else {
handle_configs::comment_directive($printer->{cupsconfig}{cupsd_conf},
- 'BrowseAddress')
+ 'BrowseAddress');
}
# Set "BrowseAllow" lines
if ($#{$printer->{cupsconfig}{clientnetworks}} >= 0) {
@@ -1358,6 +1580,35 @@ sub clean_cups_config {
}
#----------------------------------------------------------------------
+# Handling of /etc/cups/client.conf
+
+sub read_client_conf() {
+ return (0, undef) if (! -r "$::prefix/etc/cups/client.conf");
+ my @client_conf = cat_("$::prefix/etc/cups/client.conf");
+ my @servers = handle_configs::read_directives(\@client_conf,
+ "ServerName");
+ return (@servers > 0,
+ $servers[0]); # If there is more than one entry in client.conf,
+ # the first one counts.
+}
+
+sub write_client_conf {
+ my ($daemonless_cups, $remote_cups_server) = @_;
+ # Create the directory for client.conf if needed
+ (-d "$::prefix/etc/cups/") || mkdir("$::prefix/etc/cups/") || return 1;
+ my (@client_conf) = cat_("$::prefix/etc/cups/client.conf");
+ if ($daemonless_cups) {
+ handle_configs::set_directive(\@client_conf,
+ "ServerName $remote_cups_server");
+ } else {
+ handle_configs::comment_directive(\@client_conf, "ServerName");
+ }
+ output("$::prefix/etc/cups/client.conf", @client_conf);
+}
+
+
+
+#----------------------------------------------------------------------
sub read_printers_conf {
my ($printer) = @_;
my $current;
@@ -1369,9 +1620,9 @@ sub read_printers_conf {
#- Location > Location Text
#- State > Idle|Stopped
#- Accepting > Yes|No
- local *PRINTERS; open PRINTERS, "$::prefix/etc/cups/printers.conf" or return;
+ open(my $PRINTERS, "$::prefix/etc/cups/printers.conf") or return;
local $_;
- while (<PRINTERS>) {
+ while (<$PRINTERS>) {
chomp;
/^\s*#/ and next;
if (/^\s*<(?:DefaultPrinter|Printer)\s+([^>]*)>/) { $current = { mode => 'cups', QUEUE => $1, } }
@@ -1379,7 +1630,7 @@ sub read_printers_conf {
add2hash($printer->{configured}{$current->{QUEUE}} ||= {}, $current); $current = undef }
elsif (/\s*(\S*)\s+(.*)/) { $current->{$1} = $2 }
}
- close PRINTERS;
+ close $PRINTERS;
#- assume this printing system.
$printer->{SPOOLER} ||= 'cups';
@@ -1388,12 +1639,12 @@ sub read_printers_conf {
sub get_direct_uri() {
#- get the local printer to access via a Device URI.
my @direct_uri;
- local *F; open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . "/usr/sbin/lpinfo -v |";
+ open(my $F, ($::testing ? $::prefix : "chroot $::prefix/ ") . "/usr/sbin/lpinfo -v |");
local $_;
- while (<F>) {
+ while (<$F>) {
/^(direct|usb|serial)\s+(\S*)/ and push @direct_uri, $2;
}
- close F;
+ close $F;
@direct_uri;
}
@@ -1413,7 +1664,7 @@ sub installppd {
mkdir_p("$::prefix/usr/share/cups/model/printerdrake");
# "cp_f()" is broken, it hangs infinitely
# cp_f($ppdfile, "$::prefix/usr/share/cups/model/printerdrake");
- run_program::rooted($::prefix, "cp", "-f", "$ppdfile",
+ run_program::rooted($::prefix, "cp", "-f", $ppdfile,
"$::prefix/usr/share/cups/model/printerdrake");
$ppdfile =~ s!^(.*)(/[^/]+)$!/usr/share/cups/model/printerdrake$2!;
chmod 0644, "$::prefix$ppdfile";
@@ -1421,10 +1672,9 @@ sub installppd {
printer::services::restart("cups") if $printer->{SPOOLER} eq "cups";
# Re-read printer database
%thedb = ();
- read_printer_db($printer, $printer->{SPOOLER});
- # Return description string of the PPD file
- my $ppdentry = get_descr_from_ppdfile($printer, $ppdfile);
- return $ppdentry;
+ # Supplying $ppdfile returns us the key for this PPD file in the
+ # so that we can point to it in the printer/driver list
+ return read_printer_db($printer, $printer->{SPOOLER}, $ppdfile);
}
sub clean_manufacturer_name {
@@ -1462,11 +1712,11 @@ sub ppd_entry_str {
$descr =~ s/Foomatic \+ Postscript/PostScript/;
} elsif ($descr =~ /Foomatic/i) {
$descr =~ s/Foomatic/GhostScript/i;
- } elsif ($descr =~ /CUPS\+GIMP-print/i) {
- $descr =~ s/CUPS\+GIMP-print/CUPS + GIMP-Print/i;
+ } elsif ($descr =~ /CUPS\+Gimp-Print/i) {
+ $descr =~ s/CUPS\+Gimp-Print/CUPS + Gimp-Print/i;
} elsif ($descr =~ /Series CUPS/i) {
$descr =~ s/Series CUPS/Series, CUPS/i;
- } elsif ($descr !~ /(PostScript|GhostScript|CUPS|Foomatic)/i) {
+ } elsif ($descr !~ /(PostScript|GhostScript|CUPS|Foomatic|PCL|PXL)/i) {
$descr .= ", PostScript";
}
# Split model and driver
@@ -1476,20 +1726,26 @@ sub ppd_entry_str {
/^\s*(Generic\s*PostScript\s*Printer)\s*,?\s*(.*)$/i ||
$descr =~
/^\s*(PostScript\s*Printer)\s*,?\s*(.*)$/i ||
- $descr =~ /^([^,]+[^,\s])\s*,?\s*(Foomatic.*)$/i ||
- $descr =~ /^([^,]+[^,\s])\s*,?\s*(GhostScript.*)$/i ||
- $descr =~ /^([^,]+[^,\s])\s*,?\s*(CUPS.*)$/i ||
- $descr =~ /^([^,]+[^,\s])\s*,?\s+(PS.*)$/i ||
+ $descr =~ /^([^,]+?)\s*,?\s*(Foomatic.*)$/i ||
+ $descr =~ /^([^,]+?)\s*,?\s*(GhostScript.*)$/i ||
+ $descr =~ /^([^,]+?)\s*,?\s*(CUPS.*)$/i ||
+ $descr =~ /^([^,]+?)\s*,\s+(PS.*)$/i ||
+ $descr =~ /^([^,]+?)\s*,\s+(PXL.*)$/i ||
+ $descr =~ /^([^,]+?)\s*,\s+(PCL.*)$/i ||
$descr =~
- /^([^,]+[^,\s])\s*,?\s*(\(v?\.?\s*\d\d\d\d\.\d\d\d\).*)$/i ||
- $descr =~ /^([^,]+[^,\s])\s*,?\s*(v\d+\.\d+.*)$/i ||
- $descr =~ /^([^,]+[^,\s])\s*,?\s*(PostScript.*)$/i ||
- $descr =~ /^([^,]+)\s*,?\s*(.+)$/) {
+ /^([^,]+?)\s*,?\s*(\(v?\.?\s*\d\d\d\d\.\d\d\d\).*)$/i ||
+ $descr =~ /^([^,]+?)\s*,?\s*(v?\.?\s*\d+\.\d+.*)$/i ||
+ $descr =~ /^([^,]+?)\s*,?\s*(PostScript.*)$/i ||
+ $descr =~ /^([^,]+?)\s*,\s*(.+?)$/) {
$model = $1;
$driver = $2;
$model =~ s/[\-\s,]+$//;
$driver =~ s/\b(PS|PostScript\b)/PostScript/gi;
$driver =~ s/(PostScript)(.*)(PostScript)/$1$2/i;
+ $driver =~ s/\b(PXL|PCL[\s\-]*(6|XL)\b)/PCL-XL/gi;
+ $driver =~ s/(PCL-XL)(.*)(PCL-XL)/$1$2/i;
+ $driver =~ s/\b(PCL[\s\-]*(|4|5|5c|5e)\b)/PCL/gi;
+ $driver =~ s/(PCL)(.*)(PCL)/$1$2/i;
$driver =~
s/^\s*(\(?v?\.?\s*\d\d\d\d\.\d\d\d\)?|v\d+\.\d+)([,\s]*)(.*?)\s*$/$3$2$1/i;
$driver =~ s/,\s*\(/ (/g;
@@ -1503,7 +1759,13 @@ sub ppd_entry_str {
} else {
# Some PPDs do not have the ", <driver>" part.
$model = $descr;
- $driver = "PostScript";
+ if ($model =~ /\b(PXL|PCL[\s\-]*(6|XL))\b/i) {
+ $driver = "PCL-XL";
+ } elsif ($model =~ /\b(PCL[\s\-]*(|4|5|5c|5e)\b)/i) {
+ $driver = "PCL";
+ } else {
+ $driver = "PostScript";
+ }
}
}
# Remove manufacturer's name from the beginning of the model
@@ -1519,7 +1781,7 @@ sub ppd_entry_str {
$model =~ s/BJC\s+/BJC-/;
}
# New MF devices from Epson have mis-spelled name in PPD files for
- # native CUPS drivers of GIMP-Print
+ # native CUPS drivers of Gimp-Print
if ($mf eq "EPSON") {
$model =~ s/Stylus CX\-/Stylus CX/;
}
@@ -1529,9 +1791,11 @@ sub ppd_entry_str {
$model =~ s/Oki\s+//i;
}
# Try again to remove manufacturer's name from the beginning of the
- # model name, this with the cleaned manufacturer name
+ # model name, this time with the cleaned manufacturer name
$model =~ s/^$mf[\s\-]+//i
if $mf && $mf !~ m![\\/\(\)\[\]\|\.\$\@\%\*\?]!;
+ # Translate "(recommended)" in the driver string
+ $driver =~ s/\(recommended\)/$precstr/gi;
# Put out the resulting description string
uc($mf) . '|' . $model . '|' . $driver .
($lang && " (" . lc(substr($lang, 0, 2)) . ")");
@@ -1557,9 +1821,9 @@ sub get_descr_from_ppdfile {
local $_;
foreach (catMaybeCompressed("$::prefix$ppdfile")) {
# "OTHERS|Generic PostScript printer|PostScript (en)";
- /^\*([^\s:]*)\s*:\s*\"([^\"]*)\"/ and
+ /^\*([^\s:]*)\s*:\s*"([^"]*)"/ and
do { $ppd{$1} = $2; next };
- /^\*([^\s:]*)\s*:\s*([^\s\"]*)/ and
+ /^\*([^\s:]*)\s*:\s*([^\s"]*)/ and
do { $ppd{$1} = $2; next };
}
};
@@ -1579,34 +1843,40 @@ sub ppd_devid_data {
$ppd = "$::prefix/usr/share/cups/model/$ppd";
my @content;
if ($ppd =~ /\.gz$/i) {
- @content = cat_("$::prefix/bin/zcat $ppd |") or return ("", "");
+ @content = cat_("$::prefix/bin/zcat $ppd |") or return "", "";
} else {
- @content = cat_($ppd) or return ("", "");
+ @content = cat_($ppd) or return "", "";
}
my ($devidmake, $devidmodel);
- /^\*Manufacturer:\s*\"(.*)\"\s*$/ and $devidmake = $1
+ /^\*Manufacturer:\s*"(.*)"\s*$/ and $devidmake = $1
foreach @content;
- /^\*Product:\s*\"\(?(.*?)\)?\"\s*$/ and $devidmodel = $1
+ /^\*Product:\s*"\(?(.*?)\)?"\s*$/ and $devidmodel = $1
foreach @content;
- return ($devidmake, $devidmodel);
+ return $devidmake, $devidmodel;
}
-sub poll_ppd_base() {
- my ($printer) = @_;
+sub poll_ppd_base {
+ my ($printer, $ppdfile) = @_;
+
+ # If a $ppdfile is supplied, we return the key of the DB entry which
+ # is for this file. This way we can pre-select a freshly added PPD in
+ # the model/driver list.
+
#- Before trying to poll the ppd database available to cups, we have
#- to make sure the file /etc/cups/ppds.dat is no more modified.
#- If cups continue to modify it (because it reads the ppd files
#- available), the poll_ppd_base program simply cores :-)
- # else cups will not be happy! and ifup lo don't run ?
+ # else cups will not be happy! and ifup lo do not run ?
run_program::rooted($::prefix, 'ifconfig', 'lo', '127.0.0.1');
printer::services::start_not_running_service("cups");
my $driversthere = scalar(keys %thedb);
+ my $ppdentry = "";
foreach (1..60) {
- local *PPDS; open PPDS, ($::testing ? $::prefix :
- "chroot $::prefix/ ") .
- "/usr/bin/poll_ppd_base -a |";
+ open(my $PPDS, ($::testing ? $::prefix :
+ "chroot $::prefix/ ") .
+ "/usr/bin/poll_ppd_base -a |");
local $_;
- while (<PPDS>) {
+ while (<$PPDS>) {
chomp;
my ($ppd, $mf, $descr, $lang) = split /\|/;
if ($ppd eq "raw") { next }
@@ -1619,20 +1889,20 @@ sub poll_ppd_base() {
$driver =~ s/\s*\([a-z]{2}(|_[A-Z]{2})\)\s*$//;
# Recommended Foomatic PPD? Extract "(recommended)"
my $isrecommended =
- $driver =~ s/\s+\(recommended\)\s*$//i;
+ $driver =~ s/\s+$sprecstr\s*$//i;
# Remove trailing white space
$driver =~ s/\s+$//;
# For Foomatic: Driver with "GhostScript + "
my $fullfoomaticdriver = $driver;
# Foomatic PPD? Extract driver name
my $isfoomatic =
- $driver =~ s/^\s*(GhostScript|Foomatic)\s*\+\s*//i;
+ $driver =~ s!^\s*(GhostScript|Foomatic)(\s*\+\s*|/)!!i;
# Foomatic PostScript driver?
$isfoomatic ||= $descr =~ /Foomatic/i;
# Native CUPS?
my $isnativecups = $driver =~ /CUPS/i;
# Native PostScript
- my $isnativeps = (!$isfoomatic and !$isnativecups);
+ my $isnativeps = !$isfoomatic && !$isnativecups;
# Key without language tag (key as it was produced for the
# entries from the Foomatic XML database)
my $keynolang = $key;
@@ -1645,10 +1915,75 @@ sub poll_ppd_base() {
# Foomatic
$key = $keynolang;
}
- if (!$printer->{expert}) {
+ my ($devidmake, $devidmodel, $deviddesc, $devidcmdset);
+ # Replace an existing printer entry if it has linked
+ # to the current PPD file.
+ my ($filename, $ppdkey);
+ $ppd =~ m!([^/]+\.ppd)(\.gz|\.bz2|)$!;
+ if (($filename = $1) &&
+ ($#{$linkedppds{$filename}} >= 0)) {
+ foreach $ppdkey (@{$linkedppds{$filename}}) {
+ next if !defined($thedb{$ppdkey});
+ # Save the autodetection data
+ $devidmake = $thedb{$ppdkey}{devidmake};
+ $devidmodel = $thedb{$ppdkey}{devidmodel};
+ $deviddesc = $thedb{$ppdkey}{deviddesc};
+ $devidcmdset = $thedb{$ppdkey}{devidcmdset};
+ # We must preserve make and model if we have one
+ # PPD for multiple printers
+ my $oldmake = $thedb{$ppdkey}{make};
+ my $oldmodel = $thedb{$ppdkey}{model};
+ # Remove the old entry
+ delete $thedb{$ppdkey};
+ my $newkey = $key;
+ if (!$printer->{expert}) {
+ # Remove driver part in recommended mode
+ $newkey =~ s/^([^\|]+\|[^\|]+)\|.*$/$1/;
+ } else {
+ # If the Foomatic entry is "recommended" let
+ # the new PPD entry be "recommended"
+ $newkey =~ s/\s*$sprecstr//g;
+ $newkey .= " $precstr"
+ if $ppdkey =~ m!$precstr!;
+ # Remove duplicate "recommended" tags and have
+ # the "recommended" tag at the end
+ $newkey =~
+ s/(\s*$sprecstr)(.*?)(\s*$sprecstr)/$2$3/;
+ $newkey =~ s/(\s*$sprecstr)(.+)$/$2$1/;
+ }
+ # If the PPD serves for multiple printers, conserve
+ # the make and model of the original entry
+ if (($#{$linkedppds{$filename}} > 0)) {
+ $newkey =~
+ s/^([^\|]+)(\|[^\|]+)(\|.*|)$/$oldmake$2$3/;
+ $newkey =~
+ s/^([^\|]+\|)([^\|]+)(\|.*|)$/$1$oldmodel$3/;
+ }
+ # Create the new entry
+ $thedb{$newkey}{ppd} = $ppd;
+ $thedb{$newkey}{make} = $mf;
+ $thedb{$newkey}{model} = $model;
+ $thedb{$newkey}{driver} = $driver;
+ # Recover saved autodetection data
+ $thedb{$newkey}{devidmake} = $devidmake
+ if $devidmake;
+ $thedb{$newkey}{devidmodel} = $devidmodel
+ if $devidmodel;
+ $thedb{$newkey}{deviddesc} = $deviddesc
+ if $deviddesc;
+ $thedb{$newkey}{devidcmdset} = $devidcmdset
+ if $devidcmdset;
+ # Rememeber which entry is the freshly added
+ # PPD file
+ $ppdentry = $newkey if
+ $ppdfile eq "/usr/share/cups/model/$ppd";
+ }
+ next;
+ } elsif (!$printer->{expert}) {
# Remove driver from printer list entry when in
# recommended mode
$key =~ s/^([^\|]+\|[^\|]+)\|.*$/$1/;
+
# Only replace an existing printer entry if
# - its driver is not the same as the driver of the
# new one
@@ -1663,18 +1998,25 @@ sub poll_ppd_base() {
if (defined($thedb{$key})) {
next if lc($thedb{$key}{driver}) eq
lc($driver);
- next unless $isnativeps &&
- $thedb{$key}{driver} =~ /^PostScript$/i ||
- $thedb{$key}{driver} ne "PPD" && $isrecommended ||
- $thedb{$key}{driver} eq "PPD" && $isrecommended && $driver ne "PostScript";
-
- # Remove the old entry
- delete $thedb{$key};
+ if ($isnativeps &&
+ $thedb{$key}{driver} =~ /^PostScript$/i ||
+ $thedb{$key}{driver} ne "PPD" && $isrecommended ||
+ $thedb{$key}{driver} eq "PPD" && $isrecommended && $driver ne "PostScript") {
+ # Save the autodetection data
+ $devidmake = $thedb{$key}{devidmake};
+ $devidmodel = $thedb{$key}{devidmodel};
+ $deviddesc = $thedb{$key}{deviddesc};
+ $devidcmdset = $thedb{$key}{devidcmdset};
+ # Remove the old entry
+ delete $thedb{$key};
+ } else {
+ next;
+ }
}
} elsif ((defined
$thedb{"$mf|$model|$fullfoomaticdriver"} ||
defined
- $thedb{"$mf|$model|$fullfoomaticdriver (recommended)"}) &&
+ $thedb{"$mf|$model|$fullfoomaticdriver $precstr"}) &&
$isfoomatic) {
# Expert mode: There is already an entry for the
# same printer/driver combo produced by the
@@ -1682,72 +2024,86 @@ sub poll_ppd_base() {
# entry
next;
} elsif (defined
- $thedb{"$mf|$model|PostScript (recommended)"} &&
+ $thedb{"$mf|$model|PostScript $precstr"} &&
$isnativeps) {
# Expert mode: "Foomatic + Postscript" driver is
# recommended and this is a PostScript PPD? Make
# this PPD the recommended one
foreach (keys
- %{$thedb{"$mf|$model|PostScript (recommended)"}}) {
+ %{$thedb{"$mf|$model|PostScript $precstr"}}) {
$thedb{"$mf|$model|PostScript"}{$_} =
- $thedb{"$mf|$model|PostScript (recommended)"}{$_};
+ $thedb{"$mf|$model|PostScript $precstr"}{$_};
}
delete
- $thedb{"$mf|$model|PostScript (recommended)"};
+ $thedb{"$mf|$model|PostScript $precstr"};
if (!$isrecommended) {
- $key .= " (recommended)";
+ $key .= " $precstr";
}
} elsif ($driver =~ /PostScript/i &&
$isrecommended && $isfoomatic &&
(my @foundkeys = grep {
/^$mf\|$model\|/ && !/CUPS/i &&
- $thedb{$_}{driver} eq "PPD"
+ $thedb{$_}{driver} eq "PPD";
} keys %thedb)) {
# Expert mode: "Foomatic + Postscript" driver is
# recommended and there was a PostScript PPD? Make
# the PostScript PPD the recommended one
my $firstfound = $foundkeys[0];
- if (!(any { /\(recommended\)/ } @foundkeys)) {
+ if (!(any { /$sprecstr/ } @foundkeys)) {
# Do it only if none of the native PostScript
# PPDs for this printer is already "recommended"
foreach (keys %{$thedb{$firstfound}}) {
- $thedb{"$firstfound (recommended)"}{$_} =
+ $thedb{"$firstfound $precstr"}{$_} =
$thedb{$firstfound}{$_};
}
delete $thedb{$firstfound};
}
- $key =~ s/\s*\(recommended\)//;
+ $key =~ s/\s*$sprecstr//;
} elsif ($driver !~ /PostScript/i &&
$isrecommended && $isfoomatic &&
(@foundkeys = grep {
- /^$mf\|$model\|.*\(recommended\)/ &&
- !/CUPS/i && $thedb{$_}{driver} eq "PPD"
+ /^$mf\|$model\|.*$sprecstr/ &&
+ !/CUPS/i && $thedb{$_}{driver} eq "PPD";
} keys %thedb)) {
# Expert mode: Foomatic driver other than "Foomatic +
# Postscript" is recommended and there was a PostScript
- # PPD which was recommended? Make The Foomatic driver
+ # PPD which was recommended? Make the Foomatic driver
# the recommended one
foreach my $sourcekey (@foundkeys) {
# Remove the "recommended" tag
my $destkey = $sourcekey;
- $destkey =~ s/\s+\(recommended\)\s*$//i;
+ $destkey =~ s/\s+$sprecstr\s*$//i;
foreach (keys %{$thedb{$sourcekey}}) {
$thedb{$destkey}{$_} = $thedb{$sourcekey}{$_};
}
delete $thedb{$sourcekey};
}
}
+
+ # Remove duplicate "recommended" tags and have the
+ # "recommended" tag at the end
+ $key =~ s/(\s*$sprecstr)(.*?)(\s*$sprecstr)/$2$3/;
+ $key =~ s/(\s*$sprecstr)(.+)$/$2$1/;
+ # Create the new entry
$thedb{$key}{ppd} = $ppd;
$thedb{$key}{make} = $mf;
$thedb{$key}{model} = $model;
$thedb{$key}{driver} = $driver;
- # Get auto-detection data
+ # Recover saved autodetection data
+ $thedb{$key}{devidmake} = $devidmake if $devidmake;
+ $thedb{$key}{devidmodel} = $devidmodel if $devidmodel;
+ $thedb{$key}{deviddesc} = $deviddesc if $deviddesc;
+ $thedb{$key}{devidcmdset} = $devidcmdset if $devidcmdset;
+ # Get autodetection data
#my ($devidmake, $devidmodel) = ppd_devid_data($ppd);
#$thedb{$key}{devidmake} = $devidmake;
#$thedb{$key}{devidmodel} = $devidmodel;
- }
+ # Rememeber which entry is the freshly added PPD file
+ $ppdentry = $key if
+ $ppdfile eq "/usr/share/cups/model/$ppd";
+ };
}
- close PPDS;
+ close $PPDS;
scalar(keys %thedb) - $driversthere > 5 and last;
#- we have to try again running the program, wait here a little
#- before.
@@ -1756,6 +2112,7 @@ sub poll_ppd_base() {
#scalar(keys %descr_to_ppd) > 5 or
# die "unable to connect to cups server";
+ return $ppdentry;
}
@@ -1783,16 +2140,25 @@ sub configure_queue($) {
("-p", $printer->{currentqueue}{printer},
"-d", $printer->{currentqueue}{driver}) :
($printer->{currentqueue}{ppd} ?
- ("--ppd",
- ($printer->{currentqueue}{ppd} !~ m!^/! ?
- "/usr/share/cups/model/" : "") .
- $printer->{currentqueue}{ppd}) :
+ ($printer->{currentqueue}{ppd} ne '1' ?
+ ("--ppd",
+ ($printer->{currentqueue}{ppd} !~ m!^/! ?
+ "/usr/share/cups/model/" : "") .
+ $printer->{currentqueue}{ppd}) : ()) :
("-d", "raw"))),
"-N", $printer->{currentqueue}{desc},
"-L", $printer->{currentqueue}{loc},
+ if_($printer->{SPOOLER} eq "cups",
+ "--backend-dont-disable=" .
+ $printer->{currentqueue}{dd},
+ "--backend-attempts=" .
+ $printer->{currentqueue}{att},
+ "--backend-delay=" .
+ $printer->{currentqueue}{delay}),
@{$printer->{currentqueue}{options}}
- ) or return 0;;
- if ($printer->{currentqueue}{ppd}) {
+ ) or return 0;
+ if ($printer->{currentqueue}{ppd} &&
+ ($printer->{currentqueue}{ppd} ne '1')) {
# Add a comment line containing the path of the used PPD file to the
# end of the PPD file
if ($printer->{currentqueue}{ppd} ne '1') {
@@ -1801,18 +2167,12 @@ sub configure_queue($) {
}
# Make sure that queue is active
- if ($printer->{SPOOLER} ne "pdq") {
+ if ($printer->{NEW} && ($printer->{SPOOLER} ne "pdq")) {
run_program::rooted($::prefix, "foomatic-printjob",
"-s", $printer->{currentqueue}{spooler},
"-C", "up", $printer->{currentqueue}{queue});
}
- # In case of CUPS set some more useful defaults for text and image
- # printing
- if ($printer->{SPOOLER} eq "cups") {
- set_cups_special_options($printer->{currentqueue}{queue});
- }
-
# Check whether a USB printer is configured and activate USB printing if so
my $useUSB = 0;
foreach (values %{$printer->{configured}}) {
@@ -1849,6 +2209,14 @@ sub configure_queue($) {
$printer->{configured}{$printer->{currentqueue}{queue}}{args} = {};
$printer->{configured}{$printer->{currentqueue}{queue}}{args} =
$printer->{ARGS};
+
+ # In case of CUPS set some more useful defaults for text and image
+ # printing
+ if ($printer->{SPOOLER} eq "cups") {
+ set_cups_special_options($printer,
+ $printer->{currentqueue}{queue});
+ }
+
# Clean up
delete($printer->{ARGS});
$printer->{OLD_CHOICE} = "";
@@ -1859,9 +2227,19 @@ sub configure_queue($) {
return 1;
}
+sub enable_disable_queue {
+ my ($printer, $queue, $state) = @_;
+
+ if (($printer->{SPOOLER} ne "pdq") &&
+ ($printer->{SPOOLER} ne "rcups")) {
+ run_program::rooted($::prefix, "foomatic-printjob",
+ "-s", $printer->{SPOOLER},
+ "-C", ($state ? "start" : "stop"), $queue);
+ }
+}
+
sub remove_queue($$) {
- my ($printer) = $_[0];
- my ($queue) = $_[1];
+ my ($printer, $queue) = @_;
run_program::rooted($::prefix, "foomatic-configure", "-R", "-q",
"-s", $printer->{SPOOLER},
"-n", $queue);
@@ -1873,7 +2251,6 @@ sub remove_queue($$) {
$printer->{ARGS} = {};
$printer->{DBENTRY} = "";
$printer->{currentqueue} = {};
- removeprinterfromapplications($printer, $queue);
}
sub restart_queue($) {
@@ -1908,38 +2285,39 @@ sub print_pages($@) {
my $queue = $printer->{QUEUE};
my $lpr = "/usr/bin/foomatic-printjob";
my $lpq = "$lpr -Q";
+ my $spooler = $printer->{SPOOLER};
+ $spooler = "cups" if $spooler eq "rcups";
# Print the pages
foreach (@pages) {
my $page = $_;
- # Only text and PostScript can be printed directly with all spoolers,
- # images must be treated seperately
+ # Only text and PostScript can be printed directly with all
+ # spoolers, images must be treated seperately
if ($page =~ /\.jpg$/) {
- if ($printer->{SPOOLER} ne "cups") {
+ if ($spooler ne "cups") {
# Use "convert" from ImageMagick for non-CUPS spoolers
system(($::testing ? $::prefix : "chroot $::prefix/ ") .
"/usr/bin/convert $page -page 427x654+100+65 PS:- | " .
($::testing ? $::prefix : "chroot $::prefix/ ") .
- "$lpr -s $printer->{SPOOLER} -P $queue");
+ "$lpr -s $spooler -P $queue");
} else {
# Use CUPS's internal image converter with CUPS, tell it
# to let the image occupy 90% of the page size (so nothing
# gets cut off by unprintable borders)
- run_program::rooted($::prefix, $lpr, "-s", $printer->{SPOOLER},
+ run_program::rooted($::prefix, $lpr, "-s", $spooler,
"-P", $queue, "-o", "scaling=90", $page);
}
} else {
- run_program::rooted($::prefix, $lpr, "-s", $printer->{SPOOLER},
+ run_program::rooted($::prefix, $lpr, "-s", $spooler,
"-P", $queue, $page);
}
}
sleep 5; #- allow lpr to send pages.
# Check whether the job is queued
- local *F;
- open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . "$lpq -s $printer->{SPOOLER} -P $queue |";
+ open(my $F, ($::testing ? $::prefix : "chroot $::prefix/ ") . "$lpq -s $spooler -P $queue |");
my @lpq_output =
- grep { !/^no entries/ && !(/^Rank\s+Owner/ .. /^\s*$/) } <F>;
- close F;
+ grep { !/^no entries/ && !(/^Rank\s+Owner/ .. /^\s*$/) } <$F>;
+ close $F;
@lpq_output;
}
@@ -1947,10 +2325,9 @@ sub help_output {
my ($printer, $spooler) = @_;
my $queue = $printer->{QUEUE};
- local *F;
- open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . sprintf($spoolers{$spooler}{help}, $queue);
- my $helptext = join("", <F>);
- close F;
+ open(my $F, ($::testing ? $::prefix : "chroot $::prefix/ ") . sprintf($spoolers{$spooler}{help}, $queue));
+ my $helptext = join("", <$F>);
+ close $F;
$helptext ||= "Option list not available!\n";
return $helptext;
}
@@ -1982,17 +2359,19 @@ sub print_optionlist {
sub get_copiable_queues {
my ($oldspooler, $newspooler) = @_;
+ # No local queues available in daemon-less CUPS mode
+ return () if ($oldspooler eq "rcups") or ($newspooler eq "rcups");
+
my @queuelist; #- here we will list all Foomatic-generated queues
# Get queue list with foomatic-configure
- local *QUEUEOUTPUT;
- open QUEUEOUTPUT, ($::testing ? $::prefix : "chroot $::prefix/ ") .
- "foomatic-configure -Q -q -s $oldspooler |" or
+ open(my $QUEUEOUTPUT, ($::testing ? $::prefix : "chroot $::prefix/ ") .
+ "foomatic-configure -Q -q -s $oldspooler |") or
die "Could not run foomatic-configure";
my $entry = {};
my $inentry = 0;
local $_;
- while (<QUEUEOUTPUT>) {
+ while (<$QUEUEOUTPUT>) {
chomp;
if ($inentry) {
# We are inside a queue entry
@@ -2002,7 +2381,7 @@ sub get_copiable_queues {
if ($entry->{foomatic} && $entry->{spooler} eq $oldspooler) {
# Is the connection type supported by the new
# spooler?
- if ($newspooler eq "cups" && $entry->{connect} =~ /^(file|ptal|lpd|socket|smb|ipp):/ ||
+ if ($newspooler eq "cups" && $entry->{connect} =~ /^(file|hp|ptal|lpd|socket|smb|ipp):/ ||
$newspooler =~ /^(lpd|lprng)$/ && $entry->{connect} =~ /^(file|ptal|lpd|socket|smb|ncp|postpipe):/ ||
$newspooler eq "pdq" && $entry->{connect} =~ /^(file|ptal|lpd|socket):/) {
push(@queuelist, $entry->{name});
@@ -2017,7 +2396,7 @@ sub get_copiable_queues {
$entry->{connect} = $1;
}
} else {
- if (m!^\s*<queue\s+foomatic\s*=\s*\"?(\d+)\"?\s*spooler\s*=\s*\"?(\w+)\"?\s*>\s*$!) {
+ if (m!^\s*<queue\s+foomatic\s*=\s*"?(\d+)"?\s*spooler\s*=\s*"?(\w+)"?\s*>\s*$!) {
# new entry
$inentry = 1;
$entry->{foomatic} = $1;
@@ -2025,8 +2404,8 @@ sub get_copiable_queues {
}
}
}
- close QUEUEOUTPUT;
-
+ close $QUEUEOUTPUT;
+
return @queuelist;
}
@@ -2038,7 +2417,7 @@ sub copy_foomatic_queue {
"-C", $oldspooler, $oldqueue);
# In case of CUPS set some more useful defaults for text and image printing
if ($printer->{SPOOLER} eq "cups") {
- set_cups_special_options($newqueue);
+ set_cups_special_options($printer, $newqueue);
}
}
@@ -2054,7 +2433,7 @@ sub copy_foomatic_queue {
sub autodetectionentry_for_uri {
my ($uri, @autodetected) = @_;
- if ($uri =~ m!^usb://([^/]+)/([^/\?]+)(|\?serial=(\S+))$!) {
+ if ($uri =~ m!^usb://([^/]+)/([^\?]+)(|\?serial=(\S+))$!) {
# USB device with URI referring to printer model
my $make = $1;
my $model = $2;
@@ -2083,6 +2462,49 @@ sub autodetectionentry_for_uri {
return $p;
}
}
+ } elsif ($uri =~ m!^hp:/(usb|par|net)/!) {
+ # HP printer (controlled by HPLIP)
+ my $hplipdevice = $uri;
+ $hplipdevice =~ m!^hp:/(usb|par|net)/(\S+?)(\?(serial|device)=(\S+)|)$!;
+ my $bus = $1;
+ my $model = $2;
+ my $serial = undef;
+ my $device = undef;
+ if ($4 eq 'serial') {
+ $serial = $5;
+ } elsif ($4 eq 'device') {
+ $device = $5;
+ }
+ $model =~ s/_/ /g;
+ foreach my $p (@autodetected) {
+ next if (!$p->{port}) ||
+ (($p->{port} =~ m!/usb!) && ($bus ne "usb")) ||
+ (($p->{port} =~ m!/dev/(lp|par.*|printer.*)\d+!) &&
+ ($bus ne "par"));
+ next if !$p->{val}{MODEL};
+ if (uc($p->{val}{MODEL}) ne uc($model)) {
+ my $entry = hplip_device_entry($p->{port}, @autodetected);
+ next if !$entry;
+ my $m = $entry->{model};
+ $m =~ s/_/ /g;
+ next if uc($m) ne uc($model);
+ }
+ next if ($serial && !$p->{val}{SERIALNUMBER}) ||
+ (!$serial && $p->{val}{SERIALNUMBER}) ||
+ (uc($serial) ne uc($p->{val}{SERIALNUMBER}));
+ if ($device) {
+ if ($bus eq "par") {
+ $device =~ m!/dev/(lp|parport|printer/)(\d+)!;
+ my $parporthplip = $1;
+ $p->{port} =~ m!/dev/(lp|parport|printer/)(\d+)!;
+ my $parportauto = $1;
+ next if $parporthplip != $parportauto;
+ } else {
+ next if $device ne $p->{port};
+ }
+ }
+ return $p;
+ }
} elsif ($uri =~ m!^ptal://?mlc:!) {
# HP multi-function device (controlled by HPOJ)
my $ptaldevice = $uri;
@@ -2119,424 +2541,392 @@ sub autodetectionentry_for_uri {
# ------------------------------------------------------------------
#
-# Configuration of HP multi-function devices
+# Configuration of HP printers and multi-function devices with HPLIP
#
# ------------------------------------------------------------------
-sub configure_hpoj {
- my ($device, @autodetected) = @_;
+sub read_hplip_db {
- # Make the subroutines of /usr/sbin/ptal-init available
- # It's only necessary to read it at the first call of this subroutine,
- # the subroutine definitions stay valid after leaving this subroutine.
- if (!$ptalinitread) {
- local *PTALINIT;
- open PTALINIT, "$::prefix/usr/sbin/ptal-init" or do {
- die "unable to open $::prefix/usr/sbin/ptal-init";
- };
- my @ptalinitfunctions; # subroutine definitions in /usr/sbin/ptal-init
- local $_;
- while (<PTALINIT>) {
- if (m!sub main!) {
- last;
- } elsif ((m!^[^\#]!) && !(m!^\s*exec\b!)){
- # Comment lines and the "exec" line (probably obsolete
- # Red Hat workaround) are skipped.
-
- # Make the subroutines also working during installation
- if ($::isInstall) {
- s!\$::prefix!\$hpoj_prefix!g;
- s!prefix="/usr"!prefix="$::prefix/usr"!g;
- s!etcPtal="/etc/ptal"!etcPtal="$::prefix/etc/ptal"!g;
- s!varLock="/var/lock"!varLock="$::prefix/var/lock"!g;
- s!varRunPrefix="/var/run"!varRunPrefix="$::prefix/var/run"!g;
- s!/sbin/lsmod!/usr/bin/lsmod!g;
- s!/sbin/modprobe!/usr/bin/modprobe!g;
- s!/sbin/rmmod!/usr/bin/rmmod!g;
- s!(my\s*\$osPlatform\s*=\s*).*?$!$1"Linux";!g;
- s!chomp\s*\$osPlatform\s*;\s*$!!g;
- s!(my\s*\$linuxVersion\s*=\s*).*?$!$1"$kernelversion";!g;
- s!^\s*\$linuxVersion\s*=~\s*s.*$!!g;
- s!chomp\s*\$linuxVersion\s*;\s*$!!g;
- s!(my\s*\$usbprintermodule\s*=\s*).*?$!$1"$usbprintermodule";!g;
- }
- push @ptalinitfunctions, $_;
- }
- }
- close PTALINIT;
+ # Read the device database XML file which comes with the HPLIP
+ # package
+ open(my $F, "< $::prefix/usr/share/hplip/data/xml/models.xml") or
+ warn "Could not read /usr/share/hplip/data/xml/models.xml\n";
- eval "package printer::hpoj;
- @ptalinitfunctions
- sub getDevnames {
- return (%devnames)
- }
- sub getConfigInfo {
- return (%configInfo)
- }";
-
- if ($::isInstall) {
- # Needed for photo card reader detection during installation
- system("ln -s $::prefix/var/run/ptal-mlcd /var/run/ptal-mlcd");
- system("ln -s $::prefix/etc/ptal /etc/ptal");
- }
- $ptalinitread = 1;
- }
-
- # Read the HPOJ config file and check whether this device is already
- # configured
- printer::hpoj::setupVariables();
- printer::hpoj::readDeviceInfo();
-
- $device =~ m!^/dev/\S*lp(\d+)$! or
- $device =~ m!^/dev/printers/(\d+)$! or
- $device =~ m!^socket://([^:]+)$! or
- $device =~ m!^socket://([^:]+):(\d+)$!;
- my $model = $1;
- my ($model_long, $serialnumber, $serialnumber_long) = ("", "", "");
- my $cardreader = 0;
- my $device_ok = 1;
- my $bus;
- my $address_arg = "";
- my $base_address = "";
- my $hostname = "";
- my $port = $2;
- if ($device =~ /usb/) {
- $bus = "usb";
- } elsif ($device =~ /par/ ||
- $device =~ m!/dev/lp! ||
- $device =~ /printers/) {
- $bus = "par";
- $address_arg = printer::detect::parport_addr($device);
- eval "$base_address = $1" if $address_arg =~ /^\s*-base\s+(\S+)/;
- } elsif ($device =~ /socket/) {
- $bus = "hpjd";
- $hostname = $model;
- return "" if $port && ($port < 9100 || $port > 9103);
- if ($port && $port != 9100) {
- $port -= 9100;
- $hostname .= ":$port";
- }
- } else {
- return "";
- }
- if ($#autodetected < 0) {
- # Make a pseudo structure for the auto-detected data if there is
- # no auto-detected data (for example when configuring manually)
- $autodetected[0] = {
- 'port' => $device,
- 'val' => {
- 'MODEL' => N("Unknown model")
+ my $entry = {};
+ my $inentry = 0;
+ my $inrX = 0;
+ my $incomment = 0;
+ my %hplipdevices;
+ local $_;
+ while (<$F>) {
+ chomp;
+ if ($incomment) {
+ # In a comment block, skip all except the end of the comment
+ if (m!^(.*?)-->(.*)$!) {
+ # End of comment, keep rest of line
+ $_ = $2;
+ $incomment = 0;
+ } else {
+ # Skip line
+ $_ = '';
}
- };
- }
- my $devdata;
- foreach (@autodetected) {
- $device eq $_->{port} or next;
- $devdata = $_;
- # $model is for the PTAL device name, so make sure that it is unique
- # so in the case of the model name auto-detection having failed leave
- # the port number or the host name as model name.
- my $searchunknown = N("Unknown model");
- if ($_->{val}{MODEL} &&
- $_->{val}{MODEL} !~ /$searchunknown/i &&
- $_->{val}{MODEL} !~ /^\s*$/) {
- $model = $_->{val}{MODEL};
- }
- $serialnumber = $_->{val}{SERIALNUMBER};
- services::stop("hpoj") if ($bus ne "hpjd");
- # Check if the device is really an HP multi-function device
- #my $libusb = 0;
- foreach my $libusb (0, 1) {
- # Do access via libusb/user mode only if we have a USB device
- next if ($libusb && ($bus ne "usb"));
- # Preliminary workaround to make the user-mode USB devices
- # (LIDIL devices) installable as verification of the HPOJ
- # settings of these devices does not work yet. The workaround
- # will probably removed after version 9.2 of this distribution.
- # Note: This workaround leaves out the checking for a photo
- # memory card reader, but to my knowledge there are no LIDIL
- # devices with card reader yet.
- if ($libusb) {
- $device_ok = 1;
- next;
+ } else {
+ while (m/^(.*?)<!--(.*?)-->(.*)$/) {
+ # Remove one-line comments
+ $_ = $1 . $3;
}
- my $printermoduleunloaded = 0;
- if ($bus ne "hpjd") {
- if (!$libusb) {
- # Start ptal-mlcd daemon for locally connected devices
- # (kernel mode with "printer"/"usblp" module for USB).
- run_program::rooted($::prefix,
- "ptal-mlcd", "$bus:probe",
- "-device",
- $device, split(' ',$address_arg));
- } else {
- # Start ptal-mlcd daemon for user-mode USB devices
- # (all LIDIL MF devices as HP PSC 1xxx and OfficeJet
- # 4xxx)
- my $usbdev = usbdevice($_->{val});
- if (defined($usbdev)) {
- # Unload kernel module "printer"/"usblp"
- if (modules::get_probeall("usb-interface")) {
- eval(modules::unload($usbprintermodule));
- $printermoduleunloaded = 1;
- }
- # Start ptal-mlcd
- run_program::rooted($::prefix,
- "ptal-mlcd", "$bus:probe",
- "-device", $usbdev);
- } else {
- # We could not determine the USB device number,
- # so we cannot check this device in user mode
- next;
- }
- }
+ if (m/^(.*?)<!--(.*)$/) {
+ # Start of comment, keep the beginning of the line
+ $_ = $1;
+ $incomment = 1;
}
- $device_ok = 0;
- my $ptalprobedevice = $bus eq "hpjd" ? "hpjd:$hostname" : "mlc:$bus:probe";
- local *F;
- if (open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . "/usr/bin/ptal-devid $ptalprobedevice |") {
- my $devid = join("", <F>);
- close F;
- if ($devid) {
- $device_ok = 1;
- local *F;
- if (open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . "/usr/bin/ptal-devid $ptalprobedevice -long -mdl 2>/dev/null |") {
- $model_long = join("", <F>);
- close F;
- chomp $model_long;
- # If SNMP or local port auto-detection failed but
- # HPOJ auto-detection succeeded, fill in model name
- # here.
- if (!$_->{val}{MODEL} ||
- $_->{val}{MODEL} =~ /$searchunknown/i ||
- $_->{val}{MODEL} =~ /^\s*$/) {
- if ($model_long =~ /:([^:;]+);/) {
- $_->{val}{MODEL} = $1;
- $model = $_->{val}{MODEL};
- $model =~ s/ /_/g;
- }
- }
+ }
+ # Is there some non-comment part left in the line
+ if (m!\S!) {
+ if ($inentry) {
+ # We are inside a device entry
+ if ($inrX) {
+ # We are in one of the the device's <rX> sections,
+ # skip the section
+ if (m!^\s*</r\d+>\s*$!) {
+ # End of <rX> section
+ $inrX = 0;
}
- if (open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . "/usr/bin/ptal-devid $ptalprobedevice -long -sern 2>/dev/null |") { #-#
- $serialnumber_long = join("", <F>);
- close F;
- chomp $serialnumber_long;
+ } else {
+ if (m!^\s*<r\d+>\s*$!) {
+ # Start of <rX> section
+ $inrX = 1;
+ } elsif (m!^\s*</model>\s*$!) {
+ # End of device entry
+ $inentry = 0;
+ my $devidmodel;
+ if ($entry->{$devidmodel}) {
+ $devidmodel = $entry->{devidmodel};
+ $devidmodel =~ s/ /_/g;
+ } else {
+ $devidmodel = $entry->{model};
+ }
+ $hplipdevices{$devidmodel} = $entry;
+ $entry = {};
+ } elsif (m!^\s*<id>\s*([^<>]+)\s*</id>\s*$!) {
+ # Full ID string
+ my $idstr = $1;
+ $idstr =~ m!(MFG|MANUFACTURER):([^;]+);!i
+ and $entry->{devidmake} = $2;
+ $idstr =~ m!(MDL|MODEL):([^;]+);!i
+ and $entry->{devidmodel} = $2;
+ $idstr =~ m!(DES|DESCRIPTION):([^;]+);!i
+ and $entry->{deviddesc} = $2;
+ $idstr =~ m!(CMD|COMMAND\s*SET):([^;]+);!i
+ and $entry->{devidcmdset} = $2;
+ } elsif (m!^\s*<io support="(\d+)".*/>\s*$!) {
+ # Input/Output ports explicitly supported by HPLIP
+ my $ports = $1;
+ $entry->{bus}{par} = 1 if ($ports & 1);
+ $entry->{bus}{usb} = 1 if ($ports & 2);
+ $entry->{bus}{net} = 1 if ($ports & 4);
+ } elsif (m!^\s*<tech type="(\d+)"/>\s*$!) {
+ # Printing technology
+ $entry->{tech} = $1;
+ } elsif (m!^\s*<align type="(\d+)"/>\s*$!) {
+ # Head alignment type
+ $entry->{align} = $1;
+ } elsif (m!^\s*<clean type="(\d+)"/>\s*$!) {
+ # Head cleaning type
+ $entry->{clean} = $1;
+ } elsif (m!^\s*<color-cal type="(\d+)"/>\s*$!) {
+ # Color calibration type
+ $entry->{colorcal} = $1;
+ } elsif (m!^\s*<status type="(\d+)"/>\s*$!) {
+ # Status request type
+ $entry->{status} = $1;
+ } elsif (m!^\s*<scan type="(\d+)"/>\s*$!) {
+ # Scanner access type
+ $entry->{scan} = $1;
+ } elsif (m!^\s*<fax type="(\d+)"/>\s*$!) {
+ # Fax access type
+ $entry->{fax} = $1;
+ } elsif (m!^\s*<pcard type="(\d+)"/>\s*$!) {
+ # Memory card access type
+ $entry->{card} = $1;
+ } elsif (m!^\s*<copy type="(\d+)"/>\s*$!) {
+ # Copier access type
+ $entry->{copy} = $1;
}
- $cardreader = 1 if printer::hpoj::cardReaderDetected($ptalprobedevice);
}
- }
- if ($bus ne "hpjd") {
- # Stop ptal-mlcd daemon for locally connected devices
- local *F;
- if (open F, ($::testing ? $::prefix : "chroot $::prefix/ ") . qq(ps auxwww | grep "ptal-mlcd $bus:probe" | grep -v grep | )) {
- my $line = <F>;
- if ($line =~ /^\s*\S+\s+(\d+)\s+/) {
- my $pid = $1;
- kill 15, $pid;
- }
- close F;
+ } else {
+ # We are not in a printer entry
+ if (m!^\s*<\s*model\s+name=\"(\S+)\"\a*>\s*$!) {
+ $inentry = 1;
+ # HPLIP model ID
+ $entry->{model} = $1;
}
- $printermoduleunloaded &&
- eval(modules::load($usbprintermodule));
}
- last if $device_ok;
}
- printer::services::start("hpoj") if ($bus ne "hpjd");
- last;
}
- # No, it is not an HP multi-function device.
- return "" if !$device_ok;
-
- # If $model_long and $serialnumber_long stay empty, fill them with
- # $model and $serialnumber
- $model_long ||= $model;
- $serialnumber_long ||= $serialnumber;
-
- # Determine the ptal device name from already existing config files
- my $ptalprefix =
- ($bus eq "hpjd" ? "hpjd:" : "mlc:$bus:");
- my $ptaldevice = printer::hpoj::lookupDevname($ptalprefix, $model_long,
- $serialnumber_long, $base_address);
-
- # It's all done for us, the device is already configured
- return $ptaldevice if defined($ptaldevice);
-
- # Determine the ptal name for a new device
- if ($bus eq "hpjd") {
- $ptaldevice = "hpjd:$hostname";
- } else {
- $ptaldevice = $model;
- $ptaldevice =~ s![\s/]+!_!g;
- $ptaldevice = "mlc:$bus:$ptaldevice";
- }
-
- # Delete any old/conflicting devices
- printer::hpoj::deleteDevice($ptaldevice);
- if ($bus eq "par") {
- while (1) {
- my $oldDevname = printer::hpoj::lookupDevname("mlc:par:",undef,undef,$base_address);
- last unless defined($oldDevname);
- printer::hpoj::deleteDevice($oldDevname);
+ close $F;
+ return \%hplipdevices;
+}
+
+sub hplip_simple_model {
+ my ($model) = @_;
+ my $simplemodel = $model;
+ $simplemodel =~ s/[^A-Za-z0-9]//g;
+ $simplemodel =~ s/HewlettPackard/HP/gi;
+ $simplemodel =~ s/HP//gi;
+ $simplemodel =~ s/(DeskJet\d+C?)([a-z]*?)/$1/gi;
+ $simplemodel =~ s/((LaserJet|OfficeJet|PhotoSmart|PSC)\d+)([a-z]*?)/$1/gi;
+ $simplemodel =~ s/DeskJet/DJ/gi;
+ $simplemodel =~ s/PhotoSmartP/PhotoSmart/gi;
+ $simplemodel =~ s/LaserJet/LJ/gi;
+ $simplemodel =~ s/OfficeJet/OJ/gi;
+ $simplemodel =~ s/Series//gi;
+ $simplemodel = uc($simplemodel);
+ return $simplemodel;
+}
+
+sub hplip_device_entry {
+ my ($device, @autodetected) = @_;
+
+ # Currently, only local or TCP/Socket device work
+ return undef if ($device !~ /usb/i) &&
+ ($device !~ m!/dev/(lp|par.*|printer.*)\d+!) &&
+ ($device !~ m!^socket://!i);
+
+ if (!$hplipdevicesdb) {
+ # Read the HPLIP device database if not done already
+ $hplipdevicesdb = read_hplip_db();
+ }
+
+ my $entry;
+ foreach my $a (@autodetected) {
+ $device eq $a->{port} or next;
+ # Only HP devices supported
+ return undef if $a->{val}{MANUFACTURER} !~ /^\s*HP\s*$/i;
+ my $modelstr = $a->{val}{MODEL};
+ $modelstr =~ s/ /_/g;
+ if ($entry = $hplipdevicesdb->{$modelstr}) {
+ # Exact match
+ return $entry;
}
+ my $hpmodelstr = "HP_" . $modelstr;
+ if ($entry = $hplipdevicesdb->{$hpmodelstr}) {
+ # Exact match
+ return $entry;
+ }
+ my $hpmodelstr = "hp_" . $modelstr;
+ if ($entry = $hplipdevicesdb->{$hpmodelstr}) {
+ # Exact match
+ return $entry;
+ }
+ # More 'fuzzy' matching
+ my $simplemodel = hplip_simple_model($modelstr);
+ foreach my $key (keys %{$hplipdevicesdb}) {
+ my $simplekey = hplip_simple_model($key);
+ return $hplipdevicesdb->{$key} if $simplemodel eq $simplekey;
+ }
+ foreach my $key (keys %{$hplipdevicesdb}) {
+ my $simplekey = hplip_simple_model($key);
+ $simplekey =~ s/(\d\d)00(C?)$/$1\\d\\d$2/;
+ $simplekey =~ s/(\d\d\d)0(C?)$/$1\\d$2/;
+ $simplekey =~ s/(\d\d)0(\dC?)$/$1\\d$2/;
+ return $hplipdevicesdb->{$key} if
+ $simplemodel =~ m/^$simplekey$/i;
+ }
+ # Device not supported
+ return undef;
}
+ # $device not in @autodetected
+ return undef;
+}
- # Configure the device
+sub hplip_device_entry_from_uri {
+ my ($deviceuri) = @_;
- # Open configuration file
- local *CONFIG;
- open(CONFIG, "> $::prefix/etc/ptal/$ptaldevice") or
- die "Could not open /etc/ptal/$ptaldevice for writing!\n";
+ return undef if $deviceuri !~ m!^hp:/!;
+
+ if (!$hplipdevicesdb) {
+ # Read the HPLIP device database if not done already
+ $hplipdevicesdb = read_hplip_db();
+ }
- # Write file header.
- my $date = chomp_(`date`);
- print CONFIG
-qq(
-# Added $date by "printerdrake"
+ $deviceuri =~ m!^hp:/(usb|par|net)/(\S+?)(\?\S+|)$!;
+ my $model = $2;
+ return undef if !$model;
-# The basic format for this file is "key[+]=value".
-# If you say "+=" instead of "=", then the value is appended to any
-# value already defined for this key, rather than replacing it.
+ my $entry;
+ if ($entry = $hplipdevicesdb->{$model}) {
+ return $entry;
+ }
+ return undef;
+}
-# Comments must start at the beginning of the line. Otherwise, they may
-# be interpreted as being part of the value.
+sub start_hplip {
+ my ($device, $hplipentry, @autodetected) = @_;
-# If you have multiple devices and want to define options that apply to
-# all of them, then put them in the file /etc/ptal/defaults, which is read
-# in before this file.
+ # Determine connection type
+ my $bus;
+ if ($device =~ /usb/) {
+ $bus = "usb";
+ } elsif ($device =~ m!/dev/(lp|par.*|printer.*)\d+!) {
+ $bus = "par";
+ } elsif ($device =~ m!^socket://!) {
+ $bus = "net";
+ } else {
+ return undef;
+ }
-# The format version of this file:
-# ptal-init ignores devices with incorrect/missing versions.
-init.version=2
-);
+ # Start HPLIP daemons
+ printer::services::start_not_running_service("hplip");
- # Write model string.
- if ($model_long !~ /\S/) {
- print CONFIG
- "\n" .
- qq(# "printerdrake" couldn't read the model but added this device anyway:\n) .
- "# ";
+ # Determine HPLIP device URI for the CUPS queue
+ if ($bus eq "net") {
+ $device =~ m!^socket://([^:]+)(|:\d+)$!;
+ my $host = $1;
+ my $ip;
+ if ($host !~ m!^\d+\.\d+\.\d+\.\d+$!) {
+ my $addr = gethostbyname("$host");
+ my ($a,$b,$c,$d) = unpack('C4',$addr);
+ $ip = sprintf("%d.%d.%d.%d", $a, $b, $c, $d);
+ } else {
+ $ip = $host;
+ }
+ open(my $F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
+ "/bin/sh -c \"export LC_ALL=C; /usr/bin/hp-makeuri $ip\" |") or
+ die "Could not run \"/usr/bin/hp-makeuri $ip\"!";
+ while (my $line = <$F>) {
+ if ($line =~ m!(hp:/net/\S+)!) {
+ my $uri = $1;
+ close $F;
+ return $uri;
+ }
+ }
+ close $F;
} else {
- print CONFIG
- "\n" .
- "# The device model that was originally detected on this port:\n" .
- qq(# If this ever changes, then you should re-run "printerdrake"\n) .
- "# to delete and re-configure this device.\n";
- if ($bus eq "par") {
- print CONFIG
- "# Comment out if you don't care what model is really connected to this\n" .
- "# parallel port.\n";
+ foreach my $a (@autodetected) {
+ $device eq $a->{port} or next;
+ open(my $F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
+ "/bin/sh -c \"export LC_ALL=C; /usr/$lib/cups/backend/hp\" |") or
+ die "Could not run \"/usr/$lib/cups/backend/hp\"!";
+ while (my $line = <$F>) {
+ if (($line =~ m!^direct\s+(hp:/$bus/(\S+?)\?serial=(\S+))\s+!) ||
+ ($line =~ m!^direct\s+(hp:/$bus/(\S+?)\?device=()(\S+))\s+!) ||
+ ($line =~ m!^direct\s+(hp:/$bus/(\S+))\s+!)) {
+ my $uri = $1;
+ my $modelstr = $2;
+ my $serial = $3;
+ my $devicestr = $4;
+ $devicestr =~ m!/dev/(lp|parport|printer/)(\d+)!;
+ my $parporthplip = $1;
+ $device =~ m!/dev/(lp|parport|printer/)(\d+)!;
+ my $parportdevice = $1;
+ if ((uc($modelstr) eq uc($hplipentry->{model})) &&
+ (!$serial ||
+ (uc($serial) eq uc($a->{val}{SERIALNUMBER}))) &&
+ (!$devicestr ||
+ ($devicestr eq $device) ||
+ (($parporthplip ne "") &&
+ ($parportdevice ne "") &&
+ ($parporthplip == $parportdevice)))) {
+ close $F;
+ return $uri;
+ }
+ }
+ }
+ close $F;
+ last;
}
}
- print CONFIG
- qq(init.mlcd.append+=-devidmatch "$model_long"\n);
+ # HPLIP URI not found
+ return undef;
+}
- # Write serial-number string.
- if ($serialnumber_long !~ /\S/) {
- print CONFIG
- "\n" .
- "# The device's serial number is unknown.\n" .
- "# ";
- } else {
- print CONFIG
- "\n" .
- "# The serial number of the device that was originally detected on this port:\n";
- if ($bus =~ /^[pu]/) {
- print CONFIG
- "# Comment out if you want to disable serial-number matching.\n";
- }
+sub start_hplip_manual {
+
+ # Start HPLIP daemons
+ printer::services::start_not_running_service("hplip");
+
+ # Return all possible device URIs
+ open(my $F, ($::testing ? $::prefix : "chroot $::prefix/ ") .
+ "/bin/sh -c \"export LC_ALL=C; /usr/$lib/cups/backend/hp\" |") or
+ die "Could not run \"/usr/$lib/cups/backend/hp\"!";
+ my @uris;
+ while (<$F>) {
+ m!^direct\s+(hp:\S+)\s+!;
+ push(@uris, $1);
}
- print CONFIG
- qq(init.mlcd.append+=-devidmatch "$serialnumber_long"\n);
-
- if ($bus =~ /^[pu]/) {
- print CONFIG
- "\n" .
- "# Standard options passed to ptal-mlcd:\n" .
- "init.mlcd.append+=";
- if ($bus eq "usb") {
- # Important: don't put more quotes around /dev/usb/lp[0-9]*,
- # because ptal-mlcd currently does no globbing:
- print CONFIG "-device /dev/usb/lp0 /dev/usb/lp1 /dev/usb/lp2 /dev/usb/lp3 /dev/usb/lp4 /dev/usb/lp5 /dev/usb/lp6 /dev/usb/lp7 /dev/usb/lp8 /dev/usb/lp9 /dev/usb/lp10 /dev/usb/lp11 /dev/usb/lp12 /dev/usb/lp13 /dev/usb/lp14 /dev/usb/lp15";
- } elsif ($bus eq "par") {
- print CONFIG "$address_arg -device $device";
+ return @uris;
+}
+
+sub remove_hpoj_config {
+ my ($device, @autodetected) = @_;
+
+ for my $d (@autodetected) {
+ $device eq $d->{port} or next;
+ my $bus;
+ if ($device =~ /usb/) {
+ $bus = "usb";
+ } elsif ($device =~ m!/dev/(lp|par.*|printer.*)\d+!) {
+ $bus = "par";
+ } elsif ($device =~ /socket/) {
+ $bus = "hpjd";
}
- print CONFIG "\n" .
- "\n" .
- "# ptal-mlcd's remote console can be useful for debugging, but may be a\n" .
- "# security/DoS risk otherwise. In any case, it's accessible with the\n" .
- qq(# command "ptal-connect mlc:<XXX>:<YYY> -service PTAL-MLCD-CONSOLE".\n) .
- "# Uncomment the following line if you want to enable this feature for\n" .
- "# this device:\n" .
- "# init.mlcd.append+=-remconsole\n" .
- "\n" .
- "# If you need to pass any other command-line options to ptal-mlcd, then\n" .
- "# add them to the following line and uncomment the line:\n" .
- "# init.mlcd.append+=\n" .
- "\n" .
- "# By default ptal-printd is started for mlc: devices. If you use CUPS,\n" .
- "# then you may not be able to use ptal-printd, and you can uncomment the\n" .
- "# following line to disable ptal-printd for this device:\n" .
- "# init.printd.start=0\n";
- } else {
- print CONFIG
- "\n" .
- "# By default ptal-printd isn't started for hpjd: devices.\n" .
- "# If for some reason you want to start it for this device, then\n" .
- "# uncomment the following line:\n" .
- "init.printd.start=1\n";
- }
-
- print CONFIG
- "\n" .
- "# If you need to pass any additional command-line options to ptal-printd,\n" .
- "# then add them to the following line and uncomment the line:\n" .
- "# init.printd.append+=\n";
- if ($cardreader) {
- print CONFIG
- "\n" .
- "# Uncomment the following line to enable ptal-photod for this device:\n" .
- "init.photod.start=1\n" .
- "\n" .
- "# If you have more than one photo-card-capable peripheral and you want to\n" .
- "# assign particular TCP port numbers and mtools drive letters to each one,\n" .
- qq(# then change the line below to use the "-portoffset <n>" option.\n) .
- "init.photod.append+=-maxaltports 26\n";
- }
- close(CONFIG);
- printer::hpoj::readOneDevice($ptaldevice);
-
- # Restart HPOJ
- printer::services::restart("hpoj");
-
- # Return HPOJ device name to form the URI
- return $ptaldevice;
+ my $path = "$::prefix/etc/ptal";
+ opendir PTALDIR, "$path";
+ while (my $file = readdir(PTALDIR)) {
+ next if $file !~ /^(mlc:|)$bus:/;
+ $file = "$path/$file";
+ if ($bus eq "hpjd") {
+ $device =~ m!^socket://(\S+?)(:\d+|)$!;
+ my $host = $1;
+ if ($file =~ /$host/) {
+ closedir PTALDIR;
+ unlink($file) or return $file;
+ printer::services::restart("hpoj");
+ return undef;
+ }
+ } else {
+ if ((grep { /$d->{val}{MODEL}/ } chomp_(cat_($file))) &&
+ ((!$d->{val}{SERIALNUMBER}) ||
+ (grep { /$d->{val}{SERIALNUMBER}/ }
+ chomp_(cat_($file))))) {
+ closedir PTALDIR;
+ unlink($file) or return $file;
+ printer::services::restart("hpoj");
+ return undef;
+ }
+ }
+ }
+ last;
+ }
+ closedir PTALDIR;
+ return undef;
}
sub devicefound {
my ($usbid, $model, $serial) = @_;
# Compare the output of "lsusb -vv" with the elements of the device
# ID string
- if ($serial && ($usbid->{'SERIALNUMBER'} eq $serial)) {
+ if ($serial && $usbid->{SERIALNUMBER} eq $serial) {
# Match of serial number has absolute priority
return 1;
- } elsif ($model && ($usbid->{'MODEL'} eq $model)) {
+ } elsif ($model && $usbid->{MODEL} eq $model) {
# Try to match the model name otherwise
return 1;
}
return 0;
}
-sub usbdevice() {
+sub usbdevice {
my ($usbid) = @_;
- # Run "lsusb -vv¨ and search the given device to get its USB bus and
+ # Run "lsusb -vv" and search the given device to get its USB bus and
# device numbers
- local *F;
- open F, ($::testing ? "" : "chroot $::prefix/ ") .
- '/bin/sh -c "export LC_ALL=C; lsusb -vv 2> /dev/null" |'
+ open(my $F, ($::testing ? "" : "chroot $::prefix/ ") .
+ '/bin/sh -c "export LC_ALL=C; lsusb -vv 2> /dev/null" |')
or return undef;
my ($bus, $device, $model, $serial) = ("", "", "", "");
my $found = 0;
- while (my $line = <F>) {
+ while (my $line = <$F>) {
chomp $line;
if ($line =~ m/^\s*Bus\s+(\d+)\s+Device\s+(\d+)\s*:/i) {
# head line of a new device
@@ -2554,7 +2944,7 @@ sub usbdevice() {
$serial = $1;
}
}
- close F;
+ close $F;
# Check last entry
$found = devicefound($usbid, $model, $serial);
@@ -2562,102 +2952,20 @@ sub usbdevice() {
return sprintf("%%%03d%%%03d", $bus, $device);
}
-sub config_sane() {
- # Add HPOJ backend to /etc/sane.d/dll.conf if needed (no individual
- # config file /etc/sane.d/hpoj.conf necessary, the HPOJ driver finds the
- # scanner automatically)
- return if member("hpoj", chomp_(cat_("$::prefix/etc/sane.d/dll.conf")));
- eval { append_to_file("$::prefix/etc/sane.d/dll.conf", "hpoj\n") } or
- die "can't write SANE config in /etc/sane.d/dll.conf: $!";
-}
-
-sub config_photocard() {
-
- # Add definitions for the drives p:. q:, r:, and s: to /etc/mtools.conf
- cat_("$::prefix/etc/mtools.conf") !~ m/^\s*drive\s+p:/m or return;
-
- append_to_file("$::prefix/etc/mtools.conf", <<'EOF');
-# Drive definitions added for the photo card readers in HP multi-function
-# devices driven by HPOJ
-drive p: file=":0" remote
-drive q: file=":1" remote
-drive r: file=":2" remote
-drive s: file=":3" remote
-# This turns off some file system integrity checks of mtools, it is needed
-# for some photo cards.
-mtools_skip_check=1
-EOF
-
- # Generate a config file for the graphical mtools frontend MToolsFM or
- # modify the existing one
- my $mtoolsfmconf;
- if (-f "$::prefix/etc/mtoolsfm.conf") {
- $mtoolsfmconf = cat_("$::prefix/etc/mtoolsfm.conf") or die "can't read MToolsFM config in $::prefix/etc/mtoolsfm.conf: $!";
- my $alloweddrives = lc($1) if $mtoolsfmconf =~ m/^\s*DRIVES\s*=\s*\"([A-Za-z ]*)\"/m;
- foreach my $letter ("p", "q", "r", "s") {
- $alloweddrives .= $letter if $alloweddrives !~ /$letter/;
- }
- $mtoolsfmconf =~ s/^\s*DRIVES\s*=\s*"[A-Za-z ]*"/DRIVES="$alloweddrives"/m;
- $mtoolsfmconf =~ s/^\s*LEFTDRIVE\s*=\s*"[^"]*"/LEFTDRIVE="p"/m;
- #"# Fix emacs syntax highlighting
- } else {
- $mtoolsfmconf = <<'EOF';
-# MToolsFM config file. comments start with a hash sign.
-#
-# This variable sets the allowed driveletters (all lowercase). Example:
-# DRIVES="ab"
-DRIVES="apqrs"
-#
-# This variable sets the driveletter upon startup in the left window.
-# An empty string or space is for the hardisk. Example:
-# LEFTDRIVE="a"
-LEFTDRIVE="p"
-#
-# This variable sets the driveletter upon startup in the right window.
-# An empty string or space is for the hardisk. Example:
-# RIGHTDRIVE="a"
-RIGHTDRIVE=" "
-EOF
- }
- output("$::prefix/etc/mtoolsfm.conf", $mtoolsfmconf);
-}
+sub config_sane {
+ my ($backend) = @_;
-# ------------------------------------------------------------------
-#
-# Configuration of printers in applications
-#
-# ------------------------------------------------------------------
-
-sub configureapplications {
- my ($printer) = @_;
- setcupslink($printer);
- printer::office::configureoffice('Star Office', $printer);
- printer::office::configureoffice('OpenOffice.Org', $printer);
- printer::gimp::configure($printer);
-}
+ # Add HPOJ/HPLIP backend to /etc/sane.d/dll.conf if needed (no
+ # individual config file /etc/sane.d/hplip.conf or
+ # /etc/sane.d/hpoj.conf necessary, the HPLIP and HPOJ drivers find
+ # the scanner automatically)
-sub addcupsremotetoapplications {
- my ($printer, $queue) = @_;
- setcupslink($printer);
- return printer::office::add_cups_remote_to_office('Star Office', $printer, $queue) &&
- printer::office::add_cups_remote_to_office('OpenOffice.Org', $printer, $queue) &&
- printer::gimp::addcupsremoteto($printer, $queue);
-}
-
-sub removeprinterfromapplications {
- my ($printer, $queue) = @_;
- setcupslink($printer);
- return printer::office::remove_printer_from_office('Star Office', $printer, $queue) &&
- printer::office::remove_printer_from_office('OpenOffice.Org', $printer, $queue) &&
- printer::gimp::removeprinterfrom($printer, $queue);
-}
-
-sub removelocalprintersfromapplications {
- my ($printer) = @_;
- setcupslink($printer);
- printer::office::remove_local_printers_from_office('Star Office', $printer);
- printer::office::remove_local_printers_from_office('OpenOffice.Org', $printer);
- printer::gimp::removelocalprintersfrom($printer);
+ return if (! -f "$::prefix/etc/sane.d/dll.conf");
+ return if member($backend,
+ chomp_(cat_("$::prefix/etc/sane.d/dll.conf")));
+ eval { append_to_file("$::prefix/etc/sane.d/dll.conf",
+ "$backend\n") } or
+ die "can not write SANE config in /etc/sane.d/dll.conf: $!";
}
sub setcupslink {