diff options
Diffstat (limited to 'perl-install/printer.pm')
-rw-r--r-- | perl-install/printer.pm | 3306 |
1 files changed, 0 insertions, 3306 deletions
diff --git a/perl-install/printer.pm b/perl-install/printer.pm deleted file mode 100644 index 11f451442..000000000 --- a/perl-install/printer.pm +++ /dev/null @@ -1,3306 +0,0 @@ -package printer; - -# $Id$ - -#use diagnostics; -#use strict; - - -use common; -use run_program; - -#-if we are in an DrakX config -my $prefix = ""; - -#-location of the printer database in an installed system -my $PRINTER_DB_FILE = "/usr/share/foomatic/db/compiled/overview.xml"; -#-configuration directory of Foomatic -my $FOOMATICCONFDIR = "/etc/foomatic"; -#-location of the file containing the default spooler's name -my $FOOMATIC_DEFAULT_SPOOLER = "$FOOMATICCONFDIR/defaultspooler"; - -#-Did we already read the subroutines of /usr/sbin/ptal-init? -my $ptalinitread = 0; - -our %spoolers = ('ppq' => { - 'help' => "/usr/bin/lphelp %s |", - 'print_command' => 'lpr-pdq', - 'long_name' =>N("PDQ - Print, Don't Queue"), - 'short_name' => N("PDQ") - }, - 'lpd' => { - 'help' => "/usr/bin/pdq -h -P %s 2>&1 |", - 'print_command' => 'lpr-cups', - 'long_name' => N("LPD - Line Printer Daemon"), - 'short_name' => N("LPD") - }, - 'lprng' => { - 'print_command' => 'lpr-lpd', - 'long_name' => N("LPRng - LPR New Generation"), - 'short_name' => N("LPRng") - }, - 'cups' => { - 'print_command' => 'lpr-cups', - 'long_name' => N("CUPS - Common Unix Printing System"), - 'short_name' => N("CUPS") - } - ); -our %spooler_inv = map { $spooler{$_}{long_name} => $_ } keys %spoolers; - -our %shortspooler_inv = map { $spooler{$_}{short_name} => $_ } keys %spoolers; - -%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 NetWare server") => "NCP", - N("Enter a printer device URI") => "URI", - N("Pipe job into a command") => "POSTPIPE" -); -our %printer_type_inv = reverse %printer_type; - -#------------------------------------------------------------------------------ - -sub set_prefix($) { $prefix = $_[0] } - -sub default_printer_type($) { "LOCAL" } - -sub spooler { - # LPD is taken from the menu for the moment because the classic LPD is - # highly unsecure. Depending on how the GNU lpr development is going on - # LPD support can be reactivated by uncommenting the following line. - - #return @spooler_inv{qw(cups lpd lprng pdq)}; - - # LPRng is not officially supported any more since Mandrake 9.0, so - # show it only in the spooler menu when it was manually installed. - my @res; - if (files_exist((qw(/usr/lib/filters/lpf - /usr/sbin/lpd)))) { - foreach (qw(cups lprng pdq)) { push @res, $spooler_inv{$_}{long_name} }; -# {qw(cups lprng pdq)}{long_name}; - } else { - foreach (qw(cups pdq)) { push @res, $spooler_inv{$_}{long_name} }; -# return spooler_inv{qw(cups pdq)}{long_name}; - } - return @res; -} - -sub printer_type($) { - my ($printer) = @_; - foreach ($printer->{SPOOLER}) { - /cups/ && return @printer_type_inv{qw(LOCAL), - qw(LPD SOCKET SMB), - $::expert ? qw(URI) : ()}; - /lpd/ && return @printer_type_inv{qw(LOCAL LPD SOCKET SMB NCP), - $::expert ? qw(POSTPIPE URI) : ()}; - /lprng/ && return @printer_type_inv{qw(LOCAL LPD SOCKET SMB NCP), - $::expert ? qw(POSTPIPE URI) : ()}; - /pdq/ && return @printer_type_inv{qw(LOCAL LPD SOCKET), - $::expert ? qw(URI) : ()}; - } -} - -sub get_default_spooler () { - if (-f "$prefix$FOOMATIC_DEFAULT_SPOOLER") { - my $spool = cat_("$prefix$FOOMATIC_DEFAULT_SPOOLER"); - chomp $spool; - return $spool if $spool =~ /cups|lpd|lprng|pdq/; - } -} - -sub set_default_spooler ($) { - my ($printer) = @_; - # Mark the default driver in a file - output_p("$prefix$FOOMATIC_DEFAULT_SPOOLER", $printer->{SPOOLER}); -} - -sub set_permissions { - my ($file, $perms, $owner, $group) = @_; - # We only need to set the permissions during installation to be able to - # print test pages. After installation the devfsd daemon does the business - # automatically. - if (!$::isInstall) { return 1 } - if ($owner && $group) { - run_program::rooted($prefix, "/bin/chown", "$owner.$group", $file) - or die "Could not start chown!"; - } elsif ($owner) { - run_program::rooted($prefix, "/bin/chown", $owner, $file) - or die "Could not start chown!"; - } elsif ($group) { - run_program::rooted($prefix, "/bin/chgrp", $group, $file) - or die "Could not start chgrp!"; - } - run_program::rooted($prefix, "/bin/chmod", $perms, $file) - or die "Could not start chmod!"; -} - -sub restart_service ($) { - my ($service) = @_; - # Exit silently if the service is not installed - return 1 if !(-x "$prefix/etc/rc.d/init.d/$service"); - run_program::rooted($prefix, "/etc/rc.d/init.d/$service", "restart"); - if (($? >> 8) != 0) { - return 0; - } else { - # CUPS needs some time to come up. - wait_for_cups() if $service eq "cups"; - return 1; - } -} - -sub start_service ($) { - my ($service) = @_; - # Exit silently if the service is not installed - return 1 if !(-x "$prefix/etc/rc.d/init.d/$service"); - run_program::rooted($prefix, "/etc/rc.d/init.d/$service", "start"); - if (($? >> 8) != 0) { - return 0; - } else { - # CUPS needs some time to come up. - wait_for_cups() if $service eq "cups"; - return 1; - } -} - -sub start_not_running_service ($) { - my ($service) = @_; - # Exit silently if the service is not installed - return 1 if !(-x "$prefix/etc/rc.d/init.d/$service"); - run_program::rooted($prefix, "/etc/rc.d/init.d/$service", "status"); - # The exit status is not zero when the service is not running - if (($? >> 8) != 0) { - run_program::rooted($prefix, "/etc/rc.d/init.d/$service", "start"); - if (($? >> 8) != 0) { - return 0; - } else { - # CUPS needs some time to come up. - wait_for_cups() if $service eq "cups"; - return 1; - } - } else { - return 1; - } -} - -sub stop_service ($) { - my ($service) = @_; - # Exit silently if the service is not installed - return 1 if !(-x "$prefix/etc/rc.d/init.d/$service"); - run_program::rooted($prefix, "/etc/rc.d/init.d/$service", "stop"); - if (($? >> 8) != 0) { return 0 } else { return 1 } -} - -sub service_running ($) { - my ($service) = @_; - # Exit silently if the service is not installed - return 0 if !(-x "$prefix/etc/rc.d/init.d/$service"); - run_program::rooted($prefix, "/etc/rc.d/init.d/$service", "status"); - # The exit status is not zero when the service is not running - if (($? >> 8) != 0) { - return 0; - } else { - return 1; - } -} - -sub service_starts_on_boot ($) { - my ($service) = @_; - local *F; - open F, ($::testing ? $prefix : "chroot $prefix/ ") . - "/bin/sh -c \"export LC_ALL=C; /sbin/chkconfig --list $service 2>&1\" |" or - return 0; - while (my $line = <F>) { - chomp $line; - if ($line =~ /:on/) { - close F; - return 1; - } - } - close F; - return 0; -} - -sub start_service_on_boot ($) { - my ($service) = @_; - run_program::rooted($prefix, "/sbin/chkconfig", "--add", $service) - or return 0; - return 1; -} - -sub SIGHUP_daemon { - my ($service) = @_; - if ($service eq "cupsd") { $service = "cups" }; - # PDQ has no daemon, exit. - if ($service eq "pdq") { return 1 }; - # CUPS needs auto-correction for its configuration - run_program::rooted($prefix, "/usr/sbin/correctcupsconfig") if $service eq "cups"; - # Name of the daemon - my %daemons = ( - "lpr" => "lpd", - "lpd" => "lpd", - "lprng" => "lpd", - "cups" => "cupsd", - "devfs" => "devfsd", - ); - my $daemon = $daemons{$service}; - $daemon = $service if ! defined $daemon; -# if ($service eq "cups") { -# # The current CUPS (1.1.13) dies on SIGHUP, do the normal restart. -# restart_service($service); -# # CUPS needs some time to come up. -# wait_for_cups(); -# } else { - - # Send the SIGHUP - run_program::rooted($prefix, "/usr/bin/killall", "-HUP", $daemon); - if ($service eq "cups") { - # CUPS needs some time to come up. - wait_for_cups(); - } - - return 1; -} - -sub wait_for_cups { - # CUPS needs some time to come up. Wait up to 30 seconds, checking - # whether CUPS is ready. - my $cupsready = 0; - my $i; - for ($i = 0; $i < 30; $i++) { - run_program::rooted($prefix, "/usr/bin/lpstat", "-r"); - if (($? >> 8) != 0) { - # CUPS is not ready, continue - sleep 1; - } else { - # CUPS is ready, quit - $cupsready = 1; - last; - } - } - return $cupsready; -} - -sub assure_device_is_available_for_cups { - # Checks whether CUPS already "knows" a certain port, it does not - # know it usually when the appropriate kernel module is loaded - # after CUPS was started or when the printer is turned on after - # CUPS was started. CUPS 1.1.12 and newer refuses to set up queues - # on devices which it does not know, it points these queues to - # file:/dev/null instead. Restart CUPS if necessary to assure that - # CUPS knows the device. - my ($device) = @_; - my $result; - for ($i = 0; $i < 3; $i++) { - local *F; - open 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>) { - if ($line =~ /$device/) { # Found a line containing the device - # name, so CUPS knows it. - close F; - return 1; - } - } - close F; - $result = SIGHUP_daemon("cups"); - } - return $result; -} - -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 - die "Could not run \"ifconfig\"!"; - while (my $line = <F>) { - if (($line !~ /^lo\s+/) && # The loopback device can have been - # started by the spooler's startup script - ($line =~ /^(\S+)\s+/)) { # In this line starts an entry for a - # running network - close F; - return 1; - } - } - close F; - return 0; -} - -sub getSNMPModel { - - my ($host) = @_; - my $manufacturer = ""; - my $model = ""; - my $description = ""; - my $serialnumber = ""; - - # SNMP request to auto-detect model - local *F; - open F, ($::testing ? $prefix : "chroot $prefix/ ") . - "/bin/sh -c \"scli -1 -c 'show printer info' $host\" |" or - return { CLASS => 'PRINTER', - MODEL => N("Unknown Model"), - MANUFACTURER => "", - DESCRIPTION => "", - SERIALNUMBER => "" - }; - while (my $l = <F>) { - chomp $l; - if (($l =~ /^\s*Manufacturer:\s*(\S.*)$/i) && - ($l =~ /^\s*Vendor:\s*(\S.*)$/i)) { - $manufacturer = $1; - $manufacturer =~ s/Hewlett[-\s_]Packard/HP/; - $manufacturer =~ s/HEWLETT[-\s_]PACKARD/HP/; - } elsif ($l =~ /^\s*Model:\s*(\S.*)$/i) { - $model = $1; - } elsif ($l =~ /^\s*Description:\s*(\S.*)$/i) { - $description = $1; - $description =~ s/Hewlett[-\s_]Packard/HP/; - $description =~ s/HEWLETT[-\s_]PACKARD/HP/; - } elsif ($l =~ /^\s*Serial\s*Number:\s*(\S.*)$/i) { - $serialnumber = $1; - } - } - close F; - - # 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.*)$/) { - if ($manufacturer eq "") { - $manufacturer = $1; - } - if ($model eq "") { - $model = $2; - } - } - # No description field? Make one out of manufacturer and model. - } elsif ($description eq "") { - $description = "$manufacturer $model"; - } - - # We couldn't determine a model - if ($model eq "") { - $model = N("Unknown Model"); - } - - # Remove trailing spaces - $manufacturer =~ s/(\S+)\s+$/$1/; - $model =~ s/(\S+)\s+$/$1/; - $description =~ s/(\S+)\s+$/$1/; - $serialnumber =~ s/(\S+)\s+$/$1/; - - # Now we have all info for one printer - # Store this auto-detection result in the data structure - return { CLASS => 'PRINTER', - MODEL => $model, - MANUFACTURER => $manufacturer, - DESCRIPTION => $description, - SERIALNUMBER => $serialnumber - }; -} - -sub getSMBPrinterShares { - - my ($host) = @_; - - # SMB request to auto-detect shares - local *F; - open F, ($::testing ? "" : "chroot $prefix/ ") . - "/bin/sh -c \"export LC_ALL=C; smbclient -N -L $host\" |" or return (); - my $insharelist = 0; - my @shares; - while (my $l = <F>) { - chomp $l; - if ($l =~ /^\s*Sharename\s+Type\s+Comment\s*$/i) { - $insharelist = 1; - } elsif ($l =~ /^\s*Server\s+Comment\s*$/i) { - $insharelist = 0; - } elsif (($l =~ /^\s*(\S+)\s+Printer\s*(.*)$/i) && - ($insharelist)) { - my $name = $1; - my $description = $2; - $description =~ s/^(\s*)//; - push (@shares, { name => $name, description => $description }); - } - } - close F; - - return @shares; -} - -sub getIPsInLocalNetworks { - - # subroutine determines the list of all hosts reachable in the local - # networks by means of pinging the broadcast addresses. - - # Return an empty list if no network is running - if (!network_running()) { - return (); - } - - # 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 = ""; - - local *IFCONFIG_OUT; - open IFCONFIG_OUT, ($::testing ? "" : "chroot $prefix/ ") . - "/bin/sh -c \"export LC_ALL=C; ifconfig\" |" or return (); - while (my $readline = <IFCONFIG_OUT>) { - # New entry ... - if ($readline =~ /^(\S+)\s/) { - my $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; - } - } - } - close(IFCONFIG_OUT); - - 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/ ") . - "/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") { - local *F; - open F, ($::testing ? "" : "chroot $prefix/ ") . - "/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\" |" - or next; - local $_; - while (<F>) { chomp; - push @addresses, $_ if !(member($_,@addresses)) } - } - } - - @addresses; -} - -sub whatNetPrinter { - - my ($network, $smb) = @_; - - my $i; - my @res; - - # Which ports should be scanned? - my @portstoscan; - push @portstoscan, "139" if $smb; - push @portstoscan, "4010", "4020", "4030", "5503", "9100-9104" if $network; - - 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) - my @hostips = getIPsInLocalNetworks(); - return () if $#hostips < 0; - my $hostlist = join (" ", @hostips); - - # Scan network for printers, the timeout settings are there to avoid - # delays caused by machines blocking their ports with a firewall - local *F; - open F, ($::testing ? "" : "chroot $prefix/ ") . - "/bin/sh -c \"export LC_ALL=C; nmap -r -P0 --host_timeout 400 --initial_rtt_timeout 200 -p $portlist $hostlist\" |" - or return @res; - my $host = ""; - my $ip = ""; - my $port = ""; - my $modelinfo = ""; - 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) { - $host = $1; - $ip = $2; - if ($host eq "") { - $host = $ip; - } - $port = ""; - - undef $modelinfo; - - } elsif ($line =~ m/^\s*(\d+)\/\S+\s+open\s+/i) { - next if $ip eq ""; - $port = $1; - - # Now we have all info for one printer - # Store this auto-detection result in the data structure - - # Determine the protocol by the port number - - # SMB/Windows - if ($port eq "139") { - my @shares = getSMBPrinterShares($ip); - foreach my $share (@shares) { - push @res, { port => "smb://$host/$share->{name}", - val => { CLASS => 'PRINTER', - MODEL => N("Unknown Model"), - MANUFACTURER => "", - DESCRIPTION => - "$share->{description}", - SERIALNUMBER => "" - } - }; - } - } else { - if (!defined($modelinfo)) { - # SNMP request to auto-detect model - $modelinfo = getSNMPModel ($ip); - } - if (defined($modelinfo)) { - push @res, { port => "socket://$host:$port", - val => $modelinfo - }; - } - } - } - } - close F; - @res; -} - -sub spooler_in_security_level { - # Was the current spooler already added to the current security level? - my ($spooler, $level) = @_; - my $sp; - $sp = (($spooler eq "lpr") || ($spooler eq "lprng")) ? "lpd" : $spooler; - $file = "$prefix/etc/security/msec/server.$level"; - if (-f $file) { - local *F; - open F, "< $file" or return 0; - while (my $line = <F>) { - if ($line =~ /^\s*$sp\s*$/) { - close F; - return 1; - } - } - close F; - } - return 0; -} - -sub add_spooler_to_security_level { - my ($spooler, $level) = @_; - my $sp; - $sp = (($spooler eq "lpr") || ($spooler eq "lprng")) ? "lpd" : $spooler; - $file = "$prefix/etc/security/msec/server.$level"; - if (-f $file) { - local *F; - open F, ">> $file" or return 0; - print F "$sp\n"; - close F; - } - return 1; -} - -sub files_exist { - my @files = @_; - foreach my $file (@files) { - return 0 if ! -f "$prefix$file"; - } - return 1; -} - -sub set_alternative { - my ($command, $executable) = @_; - local *F; - # Read the list of executables for the given command to find the number - # of the desired executable - open F, ($::testing ? $prefix : "chroot $prefix/ ") . - "/bin/sh -c \"export LC_ALL=C; /bin/echo | update-alternatives --config $command \" |" or - die "Could not run \"update-alternatives\"!"; - my $choice = 0; - while (my $line = <F>) { - chomp $line; - if ($line =~ m/^[\* ][\+ ]\s*([0-9]+)\s+(\S+)\s*$/) { # list entry? - if ($2 eq $executable) { - $choice = $1; - last; - } - } - } - close F; - # If the executable was found, assign the command to it - if ($choice > 0) { - system(($::testing ? $prefix : "chroot $prefix/ ") . - "/bin/sh -c \"/bin/echo $choice | update-alternatives --config $command > /dev/null 2>&1\""); - } - return 1; -} - -sub pdq_panic_button { - my $setting = $_[0]; - if (-f "$prefix/usr/sbin/pdqpanicbutton") { - run_program::rooted($prefix, "/usr/sbin/pdqpanicbutton", "--$setting") - or die "Could not $setting PDQ panic buttons!"; - } -} - -sub copy_printer_params($$) { - my ($from, $to) = @_; - map { $to->{$_} = $from->{$_} } grep { $_ ne 'configured' } keys %$from; - #- avoid cycles-----------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -} - -sub getinfo($) { - my ($prefix) = @_; - my $printer = {}; - my @QUEUES; - - set_prefix($prefix); - - # Initialize $printer data structure - resetinfo($printer); - - return $printer; -} - -#------------------------------------------------------------------------------ -sub resetinfo($) { - my ($printer) = @_; - $printer->{QUEUE} = ""; - $printer->{OLD_QUEUE} = ""; - $printer->{OLD_CHOICE} = ""; - $printer->{ARGS} = ""; - $printer->{DBENTRY} = ""; - $printer->{DEFAULT} = ""; - $printer->{currentqueue} = {}; - # -check which printing system was used previously and load the information - # -about its queues - read_configured_queues($printer); -} - -sub read_configured_queues($) { - my ($printer) = @_; - my @QUEUES; - # Get the default spooler choice from the config file - $printer->{SPOOLER} ||= get_default_spooler(); - if (!$printer->{SPOOLER}) { - #- Find the first spooler where there are queues - foreach my $spooler (qw(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_running($service)) { - next; - } - # 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; - if ($service eq "pdq") { - #- Have we found queues? PDQ has no damon, so we consider - #- it in use when there are defined printer queues - if ($#QUEUES != -1) { - $printer->{SPOOLER} = $spooler; - last; - } - } else { - #- For other spoolers we have already found a running - #- daemon when we have arrived here - last; - } - } - } else { - #- Poll the queues of the current default spooler - local *F; - open F, ($::testing ? $prefix : "chroot $prefix/ ") . - "foomatic-configure -P -q -s $printer->{SPOOLER} |" or - die "Could not run foomatic-configure"; - eval (join('',(<F>))); - close F; - } - $printer->{configured} = {}; - my $i; - my $N = $#QUEUES + 1; - for ($i = 0; $i < $N; $i++) { - $printer->{configured}{$QUEUES[$i]{queuedata}{queue}} = - $QUEUES[$i]; - if ((!$QUEUES[$i]{make}) || (!$QUEUES[$i]{model})) { - if ($printer->{SPOOLER} eq "cups") { - $printer->{OLD_QUEUE} = $QUEUES[$i]{queuedata}{queue}; - my $descr = get_descr_from_ppd($printer); - $descr =~ m/^([^\|]*)\|([^\|]*)\|.*$/; - $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{make} ||= $1; - $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{model} ||= $2; - # 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 ($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'; - } - $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{driver} = 'CUPS/PPD'; - $printer->{OLD_QUEUE} = ""; - # Read out the printer's options - $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{args} = read_cups_options($QUEUES[$i]{queuedata}{queue}); - } - $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{make} ||= ""; - $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{model} ||= N("Unknown model"); - } else { - $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{make} = $QUEUES[$i]{make}; - $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{model} = $QUEUES[$i]{model}; - } - # Fill in "options" field - if (my $args = $printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{args}) { - my @options; - foreach my $arg (@{$args}) { - push(@options, "-o"); - my $optstr = $arg->{name} . "=" . $arg->{default}; - push(@options, $optstr); - } - @{$printer->{configured}{$QUEUES[$i]{queuedata}{queue}}{queuedata}{options}} = @options; - } - # Construct an entry line for tree view in main window of - # printerdrake - make_menuentry($printer, $QUEUES[$i]{queuedata}{queue}); - } -} - -sub make_menuentry { - my ($printer, $queue) = @_; - my $spooler = $shortspooler_inv{$printer->{SPOOLER}}{short_name}; - my $connect = $printer->{configured}{$queue}{queuedata}{connect}; - my $localremote; - if (($connect =~ m!^file:!) || ($connect =~ m!^ptal:/mlc:!)) { - $localremote = N("Local Printers"); - } else { - $localremote = N("Remote Printers"); - } - my $make = $printer->{configured}{$queue}{queuedata}{make}; - my $model = $printer->{configured}{$queue}{queuedata}{model}; - my $connection; - if ($connect =~ m!^file:/dev/lp(\d+)$!) { - my $number = $1; - $connection = N(" on parallel port \#%s", $number); - } elsif ($connect =~ m!^file:/dev/usb/lp(\d+)$!) { - my $number = $1; - $connection = N(", USB printer \#%s", $number); - } elsif ($connect =~ m!^ptal:/(.+)$!) { - my $ptaldevice = $1; - if ($ptaldevice =~ /^mlc:par:(\d+)$/) { - my $number = $1; - $connection = N(", multi-function device on parallel port \#%s", - $number); - } elsif ($ptaldevice =~ /^mlc:usb:/) { - $connection = N(", multi-function device on USB"); - } elsif ($ptaldevice =~ /^hpjd:/) { - $connection = N(", multi-function device on HP JetDirect"); - } else { - $connection = N(", multi-function device"); - } - } elsif ($connect =~ m!^file:(.+)$!) { - $connection = N(", printing to %s", $1); - } elsif ($connect =~ m!^lpd://([^/]+)/([^/]+)/?$!) { - $connection = N(" on LPD server \"%s\", printer \"%s\"", $2, $1); - } elsif ($connect =~ m!^socket://([^/:]+):([^/:]+)/?$!) { - $connection = N(", TCP/IP host \"%s\", port %s", $1, $2); - } elsif (($connect =~ m!^smb://([^/\@]+)/([^/\@]+)/?$!) || - ($connect =~ m!^smb://.*/([^/\@]+)/([^/\@]+)/?$!) || - ($connect =~ m!^smb://.*\@([^/\@]+)/([^/\@]+)/?$!)) { - $connection = N(" on SMB/Windows server \"%s\", share \"%s\"", $1, $2); - } elsif (($connect =~ m!^ncp://([^/\@]+)/([^/\@]+)/?$!) || - ($connect =~ m!^ncp://.*/([^/\@]+)/([^/\@]+)/?$!) || - ($connect =~ m!^ncp://.*\@([^/\@]+)/([^/\@]+)/?$!)) { - $connection = N(" on Novell server \"%s\", printer \"%s\"", $1, $2); - } elsif ($connect =~ m!^postpipe:(.+)$!) { - $connection = N(", using command %s", $1); - } else { - $connection = ($::expert ? ", URI: $connect" : ""); - } - my $sep = "!"; - $printer->{configured}{$queue}{queuedata}{menuentry} = - ($::expert ? "$spooler$sep" : "") . - "$localremote$sep$queue: $make $model$connection"; -} - -sub read_printer_db(;$) { - - my $spooler = $_[0]; - - my $dbpath = $prefix . $PRINTER_DB_FILE; - - 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 - if (!(-f $dbpath)) { - open DBPATH, ($::testing ? $prefix : "chroot $prefix/ ") . #-# - "foomatic-configure -O -q |" or - die "Could not run foomatic-configure"; - } else { - open DBPATH, $dbpath or die "An error occurred on $dbpath : $!"; #-# - } - - my $entry = {}; - my $inentry = 0; - my $indrivers = 0; - my $inautodetect = 0; - local $_; - while (<DBPATH>) { - chomp; - if ($inentry) { - # We are inside a printer entry - if ($indrivers) { - # We are inside the drivers block of a printers entry - if (m!^\s*</drivers>\s*$!) { - # End of drivers block - $indrivers = 0; - } elsif (m!^\s*<driver>(.+)</driver>\s*$!) { - push (@{$entry->{drivers}}, $1); - } - } elsif ($inautodetect) { - # We are inside the autodetect block of a printers entry - # All entries inside this block will be ignored - if (m!^.*</autodetect>\s*$!) { - # End of autodetect block - $inautodetect = 0; - } - } else { - if (m!^\s*</printer>\s*$!) { - # entry completed - $inentry = 0; - # Expert mode: - # Make one database entry per driver with the entry name - # manufacturer|model|driver - if ($::expert) { - foreach my $driver (@{$entry->{drivers}}) { - my $driverstr; - if ($driver eq "Postscript") { - $driverstr = "PostScript"; - } else { - $driverstr = "GhostScript + $driver"; - } - if ($driver eq $entry->{defaultdriver}) { - $driverstr .= " (recommended)"; - } - $entry->{ENTRY} = "$entry->{make}|$entry->{model}|$driverstr"; - $entry->{driver} = $driver; - # Duplicate contents of $entry because it is multiply entered to the database - map { $thedb{$entry->{ENTRY}}{$_} = $entry->{$_} } keys %$entry; - } - } else { - # Recommended mode - # Make one entry per printer, with the recommended - # driver (manufacturerer|model) - $entry->{ENTRY} = "$entry->{make}|$entry->{model}"; - if ($entry->{defaultdriver}) { - $entry->{driver} = $entry->{defaultdriver}; - map { $thedb{$entry->{ENTRY}}{$_} = $entry->{$_} } keys %$entry; - } - } - $entry = {}; - } elsif (m!^\s*<id>\s*([^\s<>]+)\s*</id>\s*$!) { - # Foomatic printer ID - $entry->{printer} = $1; - } elsif (m!^\s*<make>(.+)</make>\s*$!) { - # Printer manufacturer - $entry->{make} = uc($1); - } elsif (m!^\s*<model>(.+)</model>\s*$!) { - # Printer model - $entry->{model} = $1; - } elsif (m!<driver>(.+)</driver>!) { - # Printer default driver - $entry->{defaultdriver} = $1; - } elsif (m!^\s*<drivers>\s*$!) { - # Drivers block - $indrivers = 1; - @{$entry->{drivers}} = (); - } elsif (m!^\s*<autodetect>\s*$!) { - # Autodetect block - $inautodetect = 1; - } - } - } else { - if (m!^\s*<printer>\s*$!) { - # new entry - $inentry = 1; - } - } - } - close DBPATH; - - # Add raw queue - if ($spooler ne "pdq") { - $entry->{ENTRY} = N("Raw printer (No driver)"); - $entry->{driver} = "raw"; - $entry->{make} = ""; - $entry->{model} = N("Unknown model"); - map { $thedb{$entry->{ENTRY}}{$_} = $entry->{$_} } keys %$entry; - } - - #- Load CUPS driver database if CUPS is used as spooler - if (($spooler) && ($spooler eq "cups") && ($::expert)) { - - #&$install('cups-drivers') unless $::testing; - #my $w; - #if ($in) { - # $w = $in->wait_message(N("CUPS starting"), - # N("Reading CUPS drivers database...")); - #} - poll_ppd_base(); - } - - @entries_db_short = sort keys %printer::thedb; - #%descr_to_db = map { $printer::thedb{$_}{DESCR}, $_ } @entries_db_short; - #%descr_to_help = map { $printer::thedb{$_}{DESCR}, $printer::thedb{$_}{ABOUT} } @entries_db_short; - #@entry_db_description = keys %descr_to_db; - #db_to_descr = reverse %descr_to_db; - -} - -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/ ") . - "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 - die "Could not run foomatic-configure"; - eval (join('',(<F>))); - close F; - # Return the arguments field - return $COMBODATA->{args}; -} - -sub read_cups_options ($) { - my ($queue_or_file) = @_; - # Generate the option data from a CUPS PPD file/a CUPS queue - # Use the same Perl data structure as Foomatic uses to be able to - # reuse the dialog - local *F; - if ($queue_or_file =~ /.ppd.gz$/) { # compressed PPD file - open F, ($::testing ? $prefix : "chroot $prefix/ ") . #-# - "gunzip -cd $queue_or_file | lphelp - |" or return 0; - } else { # PPD file not compressed or queue - open F, ($::testing ? $prefix : "chroot $prefix/ ") . #-# - "lphelp $queue_or_file |" or return 0; - } - my $i; - my $j; - my @args; - my $line; - my $inoption = 0; - my $inchoices = 0; -# my $innumerical = 0; - while ($line = <F>) { - chomp $line; - if ($inoption) { - if ($inchoices) { - if ($line =~ /^\s*(\S+)\s+(\S.*)$/) { - push(@{$args[$i]{vals}}, {}); - $j = $#{$args[$i]{vals}}; - $args[$i]{vals}[$j]{value} = $1; - my $comment = $2; - # Did we find the default setting? - if ($comment =~ /default\)\s*$/) { - $args[$i]{default} = $args[$i]{vals}[$j]{value}; - $comment =~ s/,\s*default\)\s*$//; - } else { - $comment =~ s/\)\s*$//; - } - # Remove opening paranthese - $comment =~ s/^\(//; - # Remove page size info - $comment =~ s/,\s*size:\s*[0-9\.]+x[0-9\.]+in$//; - $args[$i]{vals}[$j]{comment} = $comment; - } elsif (($line =~ /^\s*$/) && ($#{$args[$i]{vals}} > -1)) { - $inchoices = 0; - $inoption = 0; - } -# } elsif ($innumerical == 1) { -# if ($line =~ /^\s*The default value is ([0-9\.]+)\s*$/) { -# $args[$i]{default} = $1; -# $innumerical = 0; -# $inoption = 0; -# } - } else { - if ($line =~ /^\s*<choice>/) { - $inchoices = 1; -# } elsif ($line =~ /^\s*<value> must be a(.*) number in the range ([0-9\.]+)\.\.([0-9\.]+)\s*$/) { -# delete($args[$i]{vals}); -# $args[$i]{min} = $2; -# $args[$i]{max} = $3; -# my $type = $1; -# if ($type =~ /integer/) { -# $args[$i]{type} = 'int'; -# } else { -# $args[$i]{type} = 'float'; -# } -# $innumerical = 1; - } - } - } else { - if ($line =~ /^\s*([^\s:][^:]*):\s+-o\s+([^\s=]+)=<choice>\s*$/) { -# if ($line =~ /^\s*([^\s:][^:]*):\s+-o\s+([^\s=]+)=<.*>\s*$/) { - $inoption = 1; - push(@args, {}); - $i = $#args; - $args[$i]{comment} = $1; - $args[$i]{name} = $2; - $args[$i]{type} = 'enum'; - @{$args[$i]{vals}} = (); - } - } - } - close F; - # Return the arguments field - return \@args; -} - -sub set_cups_special_options { - my ($queue) = $_[0]; - # 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 (!grep { /$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"); - } - # Let images fill the whole page by default - if (!grep { /$queue.*\s(scaling|natural-scaling|ppi)=/ } @lpoptions) { - run_program::rooted($prefix, "lpoptions", - "-p", $queue, - "-o", "scaling=100"); - } - return 1; -} - -#------------------------------------------------------------------------------ - -sub read_cups_printer_list { - my ($printer) = $_[0]; - # This function reads in a list of all printers which the local CUPS - # daemon currently knows, including remote ones. - local *F; - open F, ($::testing ? $prefix : "chroot $prefix/ ") . - "lpstat -v |" or return (); - my @printerlist; - my $line; - while ($line = <F>) { - if ($line =~ m/^\s*device\s+for\s+([^:\s]+):\s*(\S+)\s*$/) { - my $queuename = $1; - my $comment = ""; - if (($2 =~ m!^ipp://([^/:]+)[:/]!) && - (!$printer->{configured}{$queuename})) { - $comment = N("(on %s)", $1); - } else { - $comment = N("(on this machine)"); - } - push (@printerlist, "$queuename $comment"); - } - } - close F; - return @printerlist; -} - -sub get_cups_remote_queues { - my ($printer) = $_[0]; - # This function reads in a list of all remote printers which the local - # CUPS daemon knows due to broadcasting of remote servers or - # "BrowsePoll" entries in the local /etc/cups/cupsd.conf/ - local *F; - open F, ($::testing ? $prefix : "chroot $prefix/ ") . - "lpstat -v |" or return (); - my @printerlist; - my $line; - while ($line = <F>) { - if ($line =~ m/^\s*device\s+for\s+([^:\s]+):\s*(\S+)\s*$/) { - my $queuename = $1; - my $comment = ""; - if (($2 =~ m!^ipp://([^/:]+)[:/]!) && - (!$printer->{configured}{$queuename})) { - $comment = N("On CUPS server \"%s\"", $1); - my $sep = "!"; - push (@printerlist, - ($::expert ? N("CUPS") . $sep : "") . - N("Remote Printers") . "$sep$queuename: $comment" - . ($queuename eq $printer->{DEFAULT} ? - N(" (Default)") : (""))); - } - } - } - close F; - return @printerlist; -} - -sub set_cups_autoconf { - my $autoconf = $_[0]; - - # Read config file - my $file = "$prefix/etc/sysconfig/printing"; - @file_content = cat_($file); - - # Remove all valid "CUPS_CONFIG" lines - (/^\s*CUPS_CONFIG/ and $_ = "") foreach @file_content; - - # Insert the new "CUPS_CONFIG" line - if ($autoconf) { - push @file_content, "CUPS_CONFIG=automatic\n"; - } else { - push @file_content, "CUPS_CONFIG=manual\n"; - } - - output($file, @file_content); - - # Restart CUPS - restart_service("cups"); - - return 1; -} - -sub get_cups_autoconf { - local *F; - open F, "< $prefix/etc/sysconfig/printing" or return 1; - my $line; - while ($line = <F>) { - if ($line =~ m!^[^\#]*CUPS_CONFIG=manual!) { - return 0; - } - } - return 1; -} - -sub set_usermode { - my $usermode = $_[0]; - $::expert = $usermode; - - # Read config file - my $file = "$prefix/etc/sysconfig/printing"; - @file_content = cat_($file); - - # Remove all valid "USER_MODE" lines - (/^\s*USER_MODE/ and $_ = "") foreach @file_content; - - # Insert the new "USER_MODE" line - if ($usermode) { - push @file_content, "USER_MODE=expert\n"; - } else { - push @file_content, "USER_MODE=recommended\n"; - } - - output($file, @file_content); - - return 1; -} - -sub get_usermode { - local *F; - open F, "< $prefix/etc/sysconfig/printing" or return 0; - my $line; - while ($line = <F>) { - if ($line =~ m!^[^\#]*USER_MODE=expert!) { - $::expert = 1; - return 1; - } - } - $::expert = 0; - return 0; -} - -sub set_default_printer { - my ($printer) = $_[0]; - run_program::rooted($prefix, "foomatic-configure", - "-D", "-q", "-s", $printer->{SPOOLER}, - "-n", $printer->{DEFAULT}) or return 0; - return 1; -} - -sub get_default_printer { - my $printer = $_[0]; - local *F; - open F, ($::testing ? $prefix : "chroot $prefix/ ") . - "foomatic-configure -Q -q -s $printer->{SPOOLER} |" or return undef; - my $line; - while ($line = <F>) { - if ($line =~ m!^\s*<defaultqueue>(.*)</defaultqueue>\s*$!) { - return $1; - } - } - return undef; -} - -sub read_cupsd_conf { - cat_("$prefix/etc/cups/cupsd.conf"); -} -sub write_cupsd_conf { - my (@cupsd_conf) = @_; - - output("$prefix/etc/cups/cupsd.conf", @cupsd_conf); - - #- restart cups after updating configuration. - restart_service("cups"); -} - -sub read_printers_conf { - my ($printer) = @_; - my $current; - - #- read /etc/cups/printers.conf file. - #- according to this code, we are now using the following keys for each queues. - #- DeviceURI > lpd://printer6/lp - #- Info > Info Text - #- Location > Location Text - #- State > Idle|Stopped - #- Accepting > Yes|No - local *PRINTERS; open PRINTERS, "$prefix/etc/cups/printers.conf" or return; - local $_; - while (<PRINTERS>) { - chomp; - /^\s*#/ and next; - if (/^\s*<(?:DefaultPrinter|Printer)\s+([^>]*)>/) { $current = { mode => 'cups', QUEUE => $1, } } - elsif (/\s*<\/Printer>/) { $current->{QUEUE} && $current->{DeviceURI} or next; #- minimal check of synthax. - add2hash($printer->{configured}{$current->{QUEUE}} ||= {}, $current); $current = undef } - elsif (/\s*(\S*)\s+(.*)/) { $current->{$1} = $2 } - } - close PRINTERS; - - #- assume this printing system. - $printer->{SPOOLER} ||= 'cups'; -} - -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 |"; - local $_; - while (<F>) { - /^(direct|usb|serial)\s+(\S*)/ and push @direct_uri, $2; - } - close F; - @direct_uri; -} - -sub get_descr_from_ppd { - my ($printer) = @_; - my %ppd; - - #- if there is no ppd, this means this is a raw queue. - local *F; open F, "$prefix/etc/cups/ppd/$printer->{OLD_QUEUE}.ppd" or return "|" . N("Unknown model"); - # "OTHERS|Generic PostScript printer|PostScript (en)"; - local $_; - while (<F>) { - /^\*([^\s:]*)\s*:\s*\"([^\"]*)\"/ and do { $ppd{$1} = $2; next }; - /^\*([^\s:]*)\s*:\s*([^\s\"]*)/ and do { $ppd{$1} = $2; next }; - } - close F; - - my $descr = ($ppd{NickName} || $ppd{ShortNickName} || $ppd{ModelName}); - # Apply the beautifying rules of poll_ppd_base - if ($descr =~ /Foomatic \+ Postscript/) { - $descr =~ s/Foomatic \+ Postscript/PostScript/; - } elsif ($descr =~ /Foomatic/) { - $descr =~ s/Foomatic/GhostScript/; - } elsif ($descr =~ /CUPS\+GIMP-print/) { - $descr =~ s/CUPS\+GIMP-print/CUPS \+ GIMP-Print/; - } elsif ($descr =~ /Series CUPS/) { - $descr =~ s/Series CUPS/Series, CUPS/; - } elsif (!(uc($descr) =~ /POSTSCRIPT/)) { - $descr .= ", PostScript"; - } - - # Split the $descr into model and driver - my $model; - my $driver; - if ($descr =~ /^([^,]+), (.*)$/) { - $model = $1; - $driver = $2; - } else { - # Some PPDs do not have the ", <driver>" part. - $model = $descr; - $driver = "PostScript"; - } - my $make = $ppd{Manufacturer}; - my $lang = $ppd{LanguageVersion}; - - # Remove manufacturer's name from the beginning of the model name - if (($make) && ($model =~ /^$make[\s\-]+([^\s\-].*)$/)) { - $model = $1; - } - - # Put out the resulting description string - uc($make) . '|' . $model . '|' . $driver . - ($lang && (" (" . lc(substr($lang, 0, 2)) . ")")); -} - -sub poll_ppd_base { - #- 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 :-) - run_program::rooted($prefix, "ifconfig lo 127.0.0.1"); #- else cups will not be happy! and ifup lo don't run ? - start_not_running_service("cups"); - my $driversthere = scalar(keys %thedb); - foreach (1..60) { - local *PPDS; open PPDS, ($::testing ? $prefix : "chroot $prefix/ ") . "/usr/bin/poll_ppd_base -a |"; - local $_; - while (<PPDS>) { - chomp; - my ($ppd, $mf, $descr, $lang) = split /\|/; - if ($ppd eq "raw") { next } - my ($model, $driver); - if ($descr) { - if ($descr =~ /^([^,]+), (.*)$/) { - $model = $1; - $driver = $2; - } else { - # Some PPDs do not have the ", <driver>" part. - $model = $descr; - $driver = "PostScript"; - } - } - # Rename Canon "BJC XXXX" models into "BJC-XXXX" so that the models - # do not appear twice - if ($mf eq "CANON") { - $model =~ s/BJC\s+/BJC-/; - } - $ppd && $mf && $descr and do { - my $key = "$mf|$model|$driver" . ($lang && " ($lang)"); - $thedb{$key}{ppd} = $ppd; - $thedb{$key}{driver} = $driver; - $thedb{$key}{make} = $mf; - $thedb{$key}{model} = $model; - } - } - close PPDS; - scalar(keys %thedb) - $driversthere > 5 and last; - #- we have to try again running the program, wait here a little before. - sleep 1; - } - - #scalar(keys %descr_to_ppd) > 5 or die "unable to connect to cups server"; - -} - - - -#-****************************************************************************** -#- write functions -#-****************************************************************************** - -sub configure_queue($) { - my ($printer) = @_; - - if ($printer->{currentqueue}{foomatic}) { - #- Create the queue with "foomatic-configure", in case of queue - #- renaming copy the old queue - run_program::rooted($prefix, "foomatic-configure", "-q", - "-s", $printer->{currentqueue}{spooler}, - "-n", $printer->{currentqueue}{queue}, - (($printer->{currentqueue}{queue} ne - $printer->{OLD_QUEUE}) && - ($printer->{configured}{$printer->{OLD_QUEUE}}) ? - ("-C", $printer->{OLD_QUEUE}) : ()), - "-c", $printer->{currentqueue}{connect}, - "-p", $printer->{currentqueue}{printer}, - "-d", $printer->{currentqueue}{driver}, - "-N", $printer->{currentqueue}{desc}, - "-L", $printer->{currentqueue}{loc}, - @{$printer->{currentqueue}{options}} - ) or die "foomatic-configure failed"; - } elsif ($printer->{currentqueue}{ppd}) { - #- If the chosen driver is a PPD file from /usr/share/cups/model, - #- we use lpadmin to set up the queue - run_program::rooted($prefix, "lpadmin", - "-p", $printer->{currentqueue}{queue}, -# $printer->{State} eq 'Idle' && -# $printer->{Accepting} eq 'Yes' ? ("-E") : (), - "-E", - "-v", $printer->{currentqueue}{connect}, - ($printer->{currentqueue}{ppd} ne '1') ? - ("-m", $printer->{currentqueue}{ppd}) : (), - $printer->{currentqueue}{desc} ? - ("-D", $printer->{currentqueue}{desc}) : (), - $printer->{currentqueue}{loc} ? - ("-L", $printer->{currentqueue}{loc}) : (), - @{$printer->{currentqueue}{options}} - ) or die "lpadmin failed"; - # 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') { - local *F; - open F, ">> $prefix/etc/cups/ppd/$printer->{currentqueue}{queue}.ppd"; - print F "*%MDKMODELCHOICE:$printer->{currentqueue}{ppd}\n"; - } - # Copy the old queue's PPD file to the new queue when it is renamed, - # to conserve the option settings - if (($printer->{currentqueue}{queue} ne - $printer->{OLD_QUEUE}) && - ($printer->{configured}{$printer->{OLD_QUEUE}})) { - system("cp -f $prefix/etc/cups/ppd/$printer->{OLD_QUEUE}.ppd $prefix/etc/cups/ppd/$printer->{currentqueue}{queue}.ppd"); - } - } else { - # Raw queue - run_program::rooted($prefix, "foomatic-configure", "-q", - "-s", $printer->{currentqueue}{spooler}, - "-n", $printer->{currentqueue}{queue}, - "-c", $printer->{currentqueue}{connect}, - "-d", $printer->{currentqueue}{driver}, - "-N", $printer->{currentqueue}{desc}, - "-L", $printer->{currentqueue}{loc} - ) or die "foomatic-configure failed"; - } - - # Make sure that queue is active - if ($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}}) { - $useUSB ||= $_->{queuedata}{connect} =~ /usb/ || - $_->{DeviceURI} =~ /usb/; - } - $useUSB ||= ($printer->{currentqueue}{queue}{queuedata}{connect} - =~ /usb/); - if ($useUSB) { - my $f = "$prefix/etc/sysconfig/usb"; - my %usb = getVarsFromSh($f); - $usb{PRINTER} = "yes"; - setVarsInSh($f, \%usb); - } - - # Open permissions for device file when PDQ is chosen as spooler - # so normal users can print. - if ($printer->{SPOOLER} eq 'pdq') { - if ($printer->{currentqueue}{connect} =~ m!^\s*file:(\S*)\s*$!) { - set_permissions($1,"666"); - } - } - - # Make a new printer entry in the $printer structure - $printer->{configured}{$printer->{currentqueue}{queue}}{queuedata} = - {}; - copy_printer_params($printer->{currentqueue}, - $printer->{configured}{$printer->{currentqueue}{queue}}{queuedata}); - # Construct an entry line for tree view in main window of - # printerdrake - make_menuentry($printer, $printer->{currentqueue}{queue}); - - # Store the default option settings - $printer->{configured}{$printer->{currentqueue}{queue}}{args} = {}; - if ($printer->{currentqueue}{foomatic}) { - my $tmp = $printer->{OLD_QUEUE}; - $printer->{OLD_QUEUE} = $printer->{currentqueue}{queue}; - $printer->{configured}{$printer->{currentqueue}{queue}}{args} = - read_foomatic_options($printer); - $printer->{OLD_QUEUE} = $tmp; - } elsif ($printer->{currentqueue}{ppd}) { - $printer->{configured}{$printer->{currentqueue}{queue}}{args} = - read_cups_options($printer->{currentqueue}{queue}); - } - # Clean up - delete($printer->{ARGS}); - $printer->{OLD_CHOICE} = ""; - $printer->{ARGS} = {}; - $printer->{DBENTRY} = ""; - $printer->{currentqueue} = {}; -} - -sub remove_queue($$) { - my ($printer) = $_[0]; - my ($queue) = $_[1]; - run_program::rooted($prefix, "foomatic-configure", "-R", "-q", - "-s", $printer->{SPOOLER}, - "-n", $queue); - # Delete old stuff from data structure - delete $printer->{configured}{$queue}; - delete($printer->{currentqueue}); - delete($printer->{ARGS}); - $printer->{OLD_CHOICE} = ""; - $printer->{ARGS} = {}; - $printer->{DBENTRY} = ""; - $printer->{currentqueue} = {}; - removeprinterfromapplications($printer, $queue); -} - -sub restart_queue($) { - my ($printer) = @_; - my $queue = $printer->{QUEUE}; - - # Restart the daemon(s) - foreach ($printer->{SPOOLER}) { - /cups/ && do { - #- restart cups. - restart_service("cups"); - last }; - /lpr|lprng/ && do { - #- restart lpd. - foreach (("/var/spool/lpd/$queue/lock", "/var/spool/lpd/lpd.lock")) { - my $pidlpd = (cat_("$prefix$_"))[0]; - kill 'TERM', $pidlpd if $pidlpd; - unlink "$prefix$_"; - } - restart_service("lpd"); sleep 1; - last }; - } - # Kill the jobs - run_program::rooted($prefix, "foomatic-printjob", "-R", - "-s", $printer->{SPOOLER}, - "-P", $queue, "-"); - -} - -sub print_pages($@) { - my ($printer, @pages) = @_; - my $queue = $printer->{QUEUE}; - my $lpr = "/usr/bin/foomatic-printjob"; - my $lpq = "$lpr -Q"; - - # Print the pages - foreach (@pages) { - my $page = $_; - # Only text and PostScript can be printed directly with all spoolers, - # images must be treated seperately - if ($page =~ /\.jpg$/) { - if ($printer->{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"); - } 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}, - "-P", $queue, "-o", "scaling=90", $page); - } - } else { - run_program::rooted($prefix, $lpr, "-s", $printer->{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 |"; - my @lpq_output = - grep { !/^no entries/ && !(/^Rank\s+Owner/ .. /^\s*$/) } <F>; - close F; - @lpq_output; -} - -sub help_output { - my ($printer, $spooler) = @_; - my $queue = $printer->{QUEUE}; - - local *F; - open F, ($::testing ? $prefix : "chroot $prefix/ ") . sprintf($spoolers{$spooler}{help}, $queue); - $helptext = join("", <F>); - close F; - $helptext = "Option list not available!\n" if $spooler eq 'lpq' && (!$helptext || ($helptext eq "")); - return $helptext; -} - -sub print_optionlist { - my ($printer) = @_; - my $queue = $printer->{QUEUE}; - my $lpr = "/usr/bin/foomatic-printjob"; - - # Print the option list pages - if ($printer->{configured}{$queue}{queuedata}{foomatic}) { - run_program::rooted($prefix, $lpr, "-s", $printer->{SPOOLER}, - "-P", $queue, "-o", "docs", - "/etc/bashrc"); - } elsif ($printer->{configured}{$queue}{queuedata}{ppd}) { - system(($::testing ? $prefix : "chroot $prefix/ ") . - "/usr/bin/lphelp $queue | " . - ($::testing ? $prefix : "chroot $prefix/ ") . - "$lpr -s $printer->{SPOOLER} -P $queue"); - } -} - -# --------------------------------------------------------------- -# -# Spooler config stuff -# -# --------------------------------------------------------------- - -sub get_copiable_queues { - my ($oldspooler, $newspooler) = @_; - - 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 - die "Could not run foomatic-configure"; - - my $entry = {}; - my $inentry = 0; - local $_; - while (<QUEUEOUTPUT>) { - chomp; - if ($inentry) { - # We are inside a queue entry - if (m!^\s*</queue>\s*$!) { - # entry completed - $inentry = 0; - if (($entry->{foomatic}) && - ($entry->{spooler} eq $oldspooler)) { - # Is the connection type supported by the new - # spooler? - if ((($newspooler eq "cups") && - (($entry->{connect} =~ /^file:/) || - ($entry->{connect} =~ /^ptal:/) || - ($entry->{connect} =~ /^lpd:/) || - ($entry->{connect} =~ /^socket:/) || - ($entry->{connect} =~ /^smb:/) || - ($entry->{connect} =~ /^ipp:/))) || - ((($newspooler eq "lpd") || - ($newspooler eq "lprng")) && - (($entry->{connect} =~ /^file:/) || - ($entry->{connect} =~ /^ptal:/) || - ($entry->{connect} =~ /^lpd:/) || - ($entry->{connect} =~ /^socket:/) || - ($entry->{connect} =~ /^smb:/) || - ($entry->{connect} =~ /^ncp:/) || - ($entry->{connect} =~ /^postpipe:/))) || - (($newspooler eq "pdq") && - (($entry->{connect} =~ /^file:/) || - ($entry->{connect} =~ /^ptal:/) || - ($entry->{connect} =~ /^lpd:/) || - ($entry->{connect} =~ /^socket:/)))) { - push(@queuelist, $entry->{name}); - } - } - $entry = {}; - } elsif (m!^\s*<name>(.+)</name>\s*$!) { - # queue name - $entry->{name} = $1; - } elsif (m!^\s*<connect>(.+)</connect>\s*$!) { - # connection type (URI) - $entry->{connect} = $1; - } - } else { - if (m!^\s*<queue\s+foomatic\s*=\s*\"?(\d+)\"?\s*spooler\s*=\s*\"?(\w+)\"?\s*>\s*$!) { - # new entry - $inentry = 1; - $entry->{foomatic} = $1; - $entry->{spooler} = $2; - } - } - } - close QUEUEOUTPUT; - - return @queuelist; -} - -sub copy_foomatic_queue { - my ($printer, $oldqueue, $oldspooler, $newqueue) = @_; - run_program::rooted($prefix, "foomatic-configure", "-q", - "-s", $printer->{SPOOLER}, - "-n", $newqueue, - "-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); - } -} - -# ------------------------------------------------------------------ -# -# Configuration of HP multi-function devices -# -# ------------------------------------------------------------------ - -sub configure_hpoj { - my ($device, @autodetected) = @_; - - # 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!^[^\#]!) { - # 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; - } - push (@ptalinitfunctions, $_); - } - } - close PTALINIT; - - eval "@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 - setupVariables (); - 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 = ""; - my $serialnumber = ""; - my $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 =~ /\/dev\/lp/) || - ($device =~ /printers/)) { - $bus = "par"; - $address_arg = parport_addr($device); - $address_arg =~ /^\s*-base\s+(\S+)/; - eval ("$base_address = $1"); - } elsif ($device =~ /socket/) { - $bus = "hpjd"; - $hostname = $model; - return "" if $port && ($port < 9100 || $port > 9103); - if ($port && $port != 9100) { - $port -= 9100; - $hostname .= ":$port"; - } - } else { - return ""; - } - 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}; - # Check if the device is really an HP multi-function device - if ($bus ne "hpjd") { - # Start ptal-mlcd daemon for locally connected devices - stop_service("hpoj"); - run_program::rooted($prefix, - "ptal-mlcd", "$bus:probe", "-device", - $device, split(' ',$address_arg)); - } - $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; - } - } - } - 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; - } - if (cardReaderDetected ($ptalprobedevice)) { - $cardreader = 1; - } - } - } - if ($bus ne "hpjd") { - # Stop ptal-mlcd daemon for locally connected devices - local *F; - if (open F, ($::testing ? $prefix : "chroot $prefix/ ") . "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; - } - start_service("hpoj"); - } - last; - } - # No, it is not an HP multi-function device. - return "" if !$device_ok; - - # Determine the ptal device name from already existing config files - my $ptalprefix = - ($bus eq "hpjd" ? "hpjd:" : "mlc:$bus:"); - my $ptaldevice = 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 - deleteDevice ($ptaldevice); - if ($bus eq "par") { - while (1) { - my $oldDevname = lookupDevname ("mlc:par:",undef,undef, - $base_address); - if (!defined($oldDevname)) { - last; - } - deleteDevice ($oldDevname); - } - } - - # Configure the device - - # Open configuration file - local *CONFIG; - open(CONFIG,"> $prefix/etc/ptal/$ptaldevice") or - die "Could not open /etc/ptal/$ptaldevice for writing!\n"; - - # Write file header. - $_ = `date`; - chomp; - print CONFIG - "# Added $_ by \"printerdrake\".\n". - "\n". - "# The basic format for this file is \"key[+]=value\".\n". - "# If you say \"+=\" instead of \"=\", then the value is appended to any\n". - "# value already defined for this key, rather than replacing it.\n". - "\n". - "# Comments must start at the beginning of the line. Otherwise, they may\n". - "# be interpreted as being part of the value.\n". - "\n". - "# If you have multiple devices and want to define options that apply to\n". - "# all of them, then put them in the file /etc/ptal/defaults, which is read\n". - "# in before this file.\n". - "\n". - "# The format version of this file:\n". - "# ptal-init ignores devices with incorrect/missing versions.\n". - "init.version=1\n"; - - # Write model string. - if ($model_long !~ /\S/) { - print CONFIG - "\n". - "# \"printerdrake\" couldn't read the model but added this device anyway:\n". - "# "; - } else { - print CONFIG - "\n". - "# The device model that was originally detected on this port:\n". - "# 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"; - } - } - print CONFIG - "init.mlcd.append+=-devidmatch \"$model_long\"\n"; - - # 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"; - } - } - print CONFIG - "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/lp[0-9]*"; - } elsif ($bus eq "par") { - print CONFIG "$address_arg -device $device"; - } - 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". - "# 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". - "# then change the line below to use the \"-portoffset <n>\" option.\n". - "init.photod.append+=-maxaltports 26\n"; - } - close(CONFIG); - readOneDevice ($ptaldevice); - - # Restart HPOJ - restart_service("hpoj"); - - # Return HPOJ device name to form the URI - return $ptaldevice; -} - -sub parport_addr { - # auto-detect the parallel port addresses - my ($device) = @_; - $device =~ m!^/dev/lp(\d+)$! or - $device =~ m!^/dev/printers/(\d+)$!; - my $portnumber = $1; - my $parport_addresses = - `cat /proc/sys/dev/parport/parport$portnumber/base-addr`; - my $address_arg; - if ($parport_addresses =~ /^\s*(\d+)\s+(\d+)\s*$/) { - $address_arg = sprintf(" -base 0x%x -basehigh 0x%x", $1, $2); - } elsif ($parport_addresses =~ /^\s*(\d+)\s*$/) { - $address_arg = sprintf(" -base 0x%x", $1); - } else { - $address_arg = ""; - } - return $address_arg; -} - -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"))); - local *F; - open F, ">> $prefix/etc/sane.d/dll.conf" or - die "can't write SANE config in /etc/sane.d/dll.conf: $!"; - print F "hpoj\n"; - close F; -} - -sub config_photocard { - - # Add definitions for the drives p:. q:, r:, and s: to /etc/mtools.conf - my $mtoolsconf = join("", cat_("$prefix/etc/mtools.conf")); - return if $mtoolsconf =~ m/^\s*drive\s+p:/m; - my $mtoolsconf_append = " -# 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 -"; - local *F; - open F, ">> $prefix/etc/mtools.conf" or - die "can't write mtools config in /etc/mtools.conf: $!"; - print F $mtoolsconf_append; - close F; - - # 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: $!"; - $mtoolsfmconf =~ m/^\s*DRIVES\s*=\s*\"([A-Za-z ]*)\"/m; - my $alloweddrives = lc($1); - foreach my $letter ("p", "q", "r", "s") { - if ($alloweddrives !~ /$letter/) { - $alloweddrives .= $letter; - } - } - $mtoolsfmconf =~ s/^\s*DRIVES\s*=\s*\"[A-Za-z ]*\"/DRIVES=\"$alloweddrives\"/m; - $mtoolsfmconf =~ s/^\s*LEFTDRIVE\s*=\s*\"[^\"]*\"/LEFTDRIVE=\"p\"/m; - } else { - $mtoolsfmconf = "\# 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=\" \" -"; - } - output("$prefix/etc/mtoolsfm.conf", $mtoolsfmconf); -} - -# ------------------------------------------------------------------ -# -# Configuration of printers in applications -# -# ------------------------------------------------------------------ - -sub configureapplications { - my ($printer) = @_; - setcupslink ($printer); - configurestaroffice($printer); - configureopenoffice($printer); - configuregimp($printer); -} - -sub addcupsremotetoapplications { - my ($printer, $queue) = @_; - setcupslink ($printer); - return (addcupsremotetostaroffice($printer, $queue) && - addcupsremotetoopenoffice($printer, $queue) && - addcupsremotetogimp($printer, $queue)); -} - -sub removeprinterfromapplications { - my ($printer, $queue) = @_; - setcupslink ($printer); - return (removeprinterfromstaroffice($printer, $queue) && - removeprinterfromopenoffice($printer, $queue) && - removeprinterfromgimp($printer, $queue)); -} - -sub removelocalprintersfromapplications { - my ($printer) = @_; - setcupslink ($printer); - removelocalprintersfromstaroffice($printer); - removelocalprintersfromopenoffice($printer); - removelocalprintersfromgimp($printer); -} - -sub setcupslink { - my ($printer) = @_; - return 1 if !$::isInstall; - return 1 if $printer->{SPOOLER} ne "cups"; - return 1 if -d "/etc/cups/ppd"; - system("ln -sf $prefix/etc/cups /etc/cups"); - return 1; -} - -sub getcupsremotequeues { - # The following code reads in a list of all remote printers which the - # local CUPS daemon knows due to broadcasting of remote servers or - # "BrowsePoll" entries in the local /etc/cups/cupsd.conf - local *F; - open F, ($::testing ? $prefix : "chroot $prefix/ ") . - "lpstat -v |" or return (); - my @printerlist; - my $line; - while ($line = <F>) { - if ($line =~ m/^\s*device\s+for\s+([^:\s]+):\s*(\S+)\s*$/) { - my $queuename = $1; - if (($2 =~ m!^ipp://([^/:]+)[:/]!) && - (!$printer->{configured}{$queuename})) { - my $server = $1; - push (@printerlist, "$queuename|$server"); - } - } - } - close F; - return @printerlist; -} - -# ------------------------------------------------------------------ -# Star Offica/OpenOffice.org -# ------------------------------------------------------------------ - -sub configurestaroffice { - my ($printer) = @_; - # Do we have Star Office installed? - my $configfilename = findsofficeconfigfile(); - return 1 if !$configfilename; - $configfilename =~ m!^(.*)/share/xp3/Xpdefaults$!; - my $configprefix = $1; - # Load Star Office printer config file - my $configfilecontent = readsofficeconfigfile($configfilename); - # Update remote CUPS queues - if (0 && ($printer->{SPOOLER} eq "cups") && - ((-x "$prefix/usr/bin/curl") || (-x "$prefix/usr/bin/wget"))) { - my @printerlist = getcupsremotequeues(); - foreach my $listentry (@printerlist) { - next if !($listentry =~ /^([^\|]+)\|([^\|]+)$/); - my $queue = $1; - my $server = $2; - if (-x "$prefix/usr/bin/wget") { - eval(run_program::rooted - ($prefix, "/usr/bin/wget", "-O", - "/etc/foomatic/$queue.ppd", - "http://$server:631/printers/$queue.ppd")); - } else { - eval(run_program::rooted - ($prefix, "/usr/bin/curl", "-o", - "/etc/foomatic/$queue.ppd", - "http://$server:631/printers/$queue.ppd")); - } - if (-r "$prefix/etc/foomatic/$queue.ppd") { - $configfilecontent = - makestarofficeprinterentry($printer, $queue, - $configprefix, - $configfilecontent); - } - } - } - # Update local printer queues - foreach my $queue (keys(%{$printer->{configured}})) { - # Check if we have a PPD file - if (! -r "$prefix/etc/foomatic/$queue.ppd") { - if (-r "$prefix/etc/cups/ppd/$queue.ppd") { - # If we have a PPD file in the CUPS config dir, link to it - run_program::rooted($prefix, - "ln", "-sf", - "/etc/cups/ppd/$queue.ppd", - "/etc/foomatic/$queue.ppd"); - } elsif (-r "$prefix/usr/share/postscript/ppd/$queue.ppd") { - # Check PPD directory of GPR, too - run_program::rooted($prefix, - "ln", "-sf", - "/usr/share/postscript/ppd/$queue.ppd", - "/etc/foomatic/$queue.ppd"); - } else { - # No PPD file at all? We cannot set up this printer - next; - } - } - $configfilecontent = - makestarofficeprinterentry($printer, $queue, $configprefix, - $configfilecontent); - } - # Patch PostScript output to print Euro symbol correctly also for - # the "Generic Printer" - $configfilecontent = removeentry - ("ports", "default_queue=", $configfilecontent); - $configfilecontent = addentry - ("ports", - "default_queue=/usr/bin/perl -p -e \"s=16#80 /euro=16#80 /Euro=\" | /usr/bin/$lprcommand{$printer->{SPOOLER}{print_command}}", - $configfilecontent); - # Write back Star Office configuration file - return writesofficeconfigfile($configfilename, $configfilecontent); -} - -sub configureopenoffice { - my ($printer) = @_; - # Do we have OpenOffice.org installed? - my $configfilename = findopenofficeconfigfile(); - return 1 if !$configfilename; - $configfilename =~ m!^(.*)/share/psprint/psprint.conf$!; - my $configprefix = $1; - # Load OpenOffice.org printer config file - my $configfilecontent = readsofficeconfigfile($configfilename); - # Update remote CUPS queues - if (0 && ($printer->{SPOOLER} eq "cups") && - ((-x "$prefix/usr/bin/curl") || (-x "$prefix/usr/bin/wget"))) { - my @printerlist = getcupsremotequeues(); - foreach my $listentry (@printerlist) { - next if !($listentry =~ /^([^\|]+)\|([^\|]+)$/); - my $queue = $1; - my $server = $2; - if (-x "$prefix/usr/bin/wget") { - eval(run_program::rooted - ($prefix, "/usr/bin/wget", "-O", - "/etc/foomatic/$queue.ppd", - "http://$server:631/printers/$queue.ppd")); - } else { - eval(run_program::rooted - ($prefix, "/usr/bin/curl", "-o", - "/etc/foomatic/$queue.ppd", - "http://$server:631/printers/$queue.ppd")); - } - if (-r "$prefix/etc/foomatic/$queue.ppd") { - $configfilecontent = - makeopenofficeprinterentry($printer, $queue, - $configprefix, - $configfilecontent); - } - } - } - # Update local printer queues - foreach my $queue (keys(%{$printer->{configured}})) { - # Check if we have a PPD file - if (! -r "$prefix/etc/foomatic/$queue.ppd") { - if (-r "$prefix/etc/cups/ppd/$queue.ppd") { - # If we have a PPD file in the CUPS config dir, link to it - run_program::rooted($prefix, - "ln", "-sf", - "/etc/cups/ppd/$queue.ppd", - "/etc/foomatic/$queue.ppd"); - } elsif (-r "$prefix/usr/share/postscript/ppd/$queue.ppd") { - # Check PPD directory of GPR, too - run_program::rooted($prefix, - "ln", "-sf", - "/usr/share/postscript/ppd/$queue.ppd", - "/etc/foomatic/$queue.ppd"); - } else { - # No PPD file at all? We cannot set up this printer - next; - } - } - $configfilecontent = - makeopenofficeprinterentry($printer, $queue, $configprefix, - $configfilecontent); - } - # Patch PostScript output to print Euro symbol correctly also for - # the "Generic Printer" - $configfilecontent = removeentry - ("Generic Printer", "Command=", $configfilecontent); - $configfilecontent = addentry - ("Generic Printer", - "Command=/usr/bin/perl -p -e \"s=/euro /unused=/Euro /unused=\" | /usr/bin/$lprcommand{$printer->{SPOOLER}{print_command}}", - $configfilecontent); - # Write back OpenOffice.org configuration file - return writesofficeconfigfile($configfilename, $configfilecontent); -} - -sub addcupsremotetostaroffice { - my ($printer, $queue) = @_; - # Do we have Star Office installed? - my $configfilename = findsofficeconfigfile(); - return 1 if !$configfilename; - $configfilename =~ m!^(.*)/share/xp3/Xpdefaults$!; - my $configprefix = $1; - # Load Star Office printer config file - my $configfilecontent = readsofficeconfigfile($configfilename); - # Update remote CUPS queues - if (($printer->{SPOOLER} eq "cups") && - ((-x "$prefix/usr/bin/curl") || (-x "$prefix/usr/bin/wget"))) { - my @printerlist = getcupsremotequeues(); - foreach my $listentry (@printerlist) { - next if !($listentry =~ /^([^\|]+)\|([^\|]+)$/); - my $q = $1; - next if $q ne $queue; - my $server = $2; - # Remove server name from queue name - $q =~ s/^([^@]*)@.*$/$1/; - if (-x "$prefix/usr/bin/wget") { - eval(run_program::rooted - ($prefix, "/usr/bin/wget", "-O", - "/etc/foomatic/$queue.ppd", - "http://$server:631/printers/$q.ppd")); - } else { - eval(run_program::rooted - ($prefix, "/usr/bin/curl", "-o", - "/etc/foomatic/$queue.ppd", - "http://$server:631/printers/$q.ppd")); - } - # Does the file exist and is it not an error message? - if ((-r "$prefix/etc/foomatic/$queue.ppd") && - (cat_("$prefix/etc/foomatic/$queue.ppd") =~ - /^\*PPD-Adobe/)) { - $configfilecontent = - makestarofficeprinterentry($printer, $queue, - $configprefix, - $configfilecontent); - } else { - unlink ("$prefix/etc/foomatic/$queue.ppd"); - return 0; - } - last; - } - } - # Write back Star Office configuration file - return writesofficeconfigfile($configfilename, $configfilecontent); -} - -sub addcupsremotetoopenoffice { - my ($printer, $queue) = @_; - # Do we have OpenOffice.org installed? - my $configfilename = findopenofficeconfigfile(); - return 1 if !$configfilename; - $configfilename =~ m!^(.*)/share/psprint/psprint.conf$!; - my $configprefix = $1; - # Load OpenOffice.org printer config file - my $configfilecontent = readsofficeconfigfile($configfilename); - # Update remote CUPS queues - if (($printer->{SPOOLER} eq "cups") && - ((-x "$prefix/usr/bin/curl") || (-x "$prefix/usr/bin/wget"))) { - my @printerlist = getcupsremotequeues(); - foreach my $listentry (@printerlist) { - next if !($listentry =~ /^([^\|]+)\|([^\|]+)$/); - my $q = $1; - next if $q ne $queue; - my $server = $2; - # Remove server name from queue name - $q =~ s/^([^@]*)@.*$/$1/; - if (-x "$prefix/usr/bin/wget") { - eval(run_program::rooted - ($prefix, "/usr/bin/wget", "-O", - "/etc/foomatic/$queue.ppd", - "http://$server:631/printers/$q.ppd")); - } else { - eval(run_program::rooted - ($prefix, "/usr/bin/curl", "-o", - "/etc/foomatic/$queue.ppd", - "http://$server:631/printers/$q.ppd")); - } - # Does the file exist and is it not an error message? - if ((-r "$prefix/etc/foomatic/$queue.ppd") && - (cat_("$prefix/etc/foomatic/$queue.ppd") =~ - /^\*PPD-Adobe/)) { - $configfilecontent = - makeopenofficeprinterentry($printer, $queue, - $configprefix, - $configfilecontent); - } else { - unlink ("$prefix/etc/foomatic/$queue.ppd"); - return 0; - } - } - } - # Write back OpenOffice.org configuration file - return writesofficeconfigfile($configfilename, $configfilecontent); -} - -sub removeprinterfromstaroffice { - my ($printer, $queue) = @_; - # Do we have Star Office installed? - my $configfilename = findsofficeconfigfile(); - return 1 if !$configfilename; - $configfilename =~ m!^(.*)/share/xp3/Xpdefaults$!; - my $configprefix = $1; - # Load Star Office printer config file - my $configfilecontent = readsofficeconfigfile($configfilename); - # Remove the printer entry - $configfilecontent = - removestarofficeprinterentry($printer, $queue, $configprefix, - $configfilecontent); - # Write back Star Office configuration file - return writesofficeconfigfile($configfilename, $configfilecontent); -} - -sub removeprinterfromopenoffice { - my ($printer, $queue) = @_; - # Do we have OpenOffice.org installed? - my $configfilename = findopenofficeconfigfile(); - return 1 if !$configfilename; - $configfilename =~ m!^(.*)/share/psprint/psprint.conf$!; - my $configprefix = $1; - # Load OpenOffice.org printer config file - my $configfilecontent = readsofficeconfigfile($configfilename); - # Remove the printer entry - $configfilecontent = - removeopenofficeprinterentry($printer, $queue, $configprefix, - $configfilecontent); - # Write back OpenOffice.org configuration file - return writesofficeconfigfile($configfilename, $configfilecontent); -} - -sub removelocalprintersfromstaroffice { - my ($printer) = @_; - # Do we have Star Office installed? - my $configfilename = findsofficeconfigfile(); - return 1 if !$configfilename; - $configfilename =~ m!^(.*)/share/xp3/Xpdefaults$!; - my $configprefix = $1; - # Load Star Office printer config file - my $configfilecontent = readsofficeconfigfile($configfilename); - # Remove the printer entries - foreach my $queue (keys(%{$printer->{configured}})) { - $configfilecontent = - removestarofficeprinterentry($printer, $queue, $configprefix, - $configfilecontent); - } - # Write back Star Office configuration file - return writesofficeconfigfile($configfilename, $configfilecontent); -} - -sub removelocalprintersfromopenoffice { - my ($printer) = @_; - # Do we have OpenOffice.org installed? - my $configfilename = findopenofficeconfigfile(); - return 1 if !$configfilename; - $configfilename =~ m!^(.*)/share/psprint/psprint.conf$!; - my $configprefix = $1; - # Load OpenOffice.org printer config file - my $configfilecontent = readsofficeconfigfile($configfilename); - # Remove the printer entries - foreach my $queue (keys(%{$printer->{configured}})) { - $configfilecontent = - removeopenofficeprinterentry($printer, $queue, $configprefix, - $configfilecontent); - } - # Write back OpenOffice.org configuration file - return writesofficeconfigfile($configfilename, $configfilecontent); -} - -sub makestarofficeprinterentry { - my ($printer, $queue, $configprefix, $configfile) = @_; - # Set default printer - if ($queue eq $printer->{DEFAULT}) { - $configfile = removeentry("windows", "device=", $configfile); - $configfile = addentry("windows", - "device=$queue,$queue PostScript,$queue", - $configfile); - } - # Make an entry in the "[devices]" section - $configfile = removeentry("devices", "$queue=", $configfile); - $configfile = addentry("devices", - "$queue=$queue PostScript,$queue", - $configfile); - # Make an entry in the "[ports]" section - # The "perl" command patches the PostScript output to print the Euro - # symbol correctly. - $configfile = removeentry("ports", "$queue=", $configfile); - $configfile = addentry("ports", - "$queue=/usr/bin/perl -p -e \"s=16#80 /euro=16#80 /Euro=\" | /usr/bin/$lprcommand{$printer->{SPOOLER}{print_command}} -P $queue", - $configfile); - # Make printer's section - $configfile = addsection("$queue,PostScript,$queue", $configfile); - # Load PPD file - my $ppd = cat_("$prefix/etc/foomatic/$queue.ppd"); - # Set the PostScript level - my $pslevel; - if ($ppd =~ /^\s*\*LanguageLevel:\s*\"?([^\s\"]+)\"?\s*$/m) { - $pslevel = $1; - $pslevel = "2" if $pslevel eq "3"; - } else { - $pslevel = "2"; - } - $configfile = removeentry("$queue.PostScript.$queue", - "Level=", $configfile); - $configfile = addentry("$queue.PostScript.$queue", - "Level=$pslevel", $configfile); - # Set Color/BW - my $color; - if ($ppd =~ /^\s*\*ColorDevice:\s*\"?([Tt]rue)\"?\s*$/m) { - $color = "1"; - } else { - $color = "0"; - } - $configfile = removeentry("$queue.PostScript.$queue", - "BitmapColor=", $configfile); - $configfile = addentry("$queue.PostScript.$queue", - "BitmapColor=$color", $configfile); - # Set the default paper size - if ($ppd =~ /^\s*\*DefaultPageSize:\s*(\S+)\s*$/m) { - my $papersize = $1; - $configfile = removeentry("$queue.PostScript.$queue", - "PageSize=", $configfile); - $configfile = removeentry("$queue.PostScript.$queue", - "PPD_PageSize=", $configfile); - $configfile = addentry("$queue.PostScript.$queue", - "PageSize=$papersize", $configfile); - $configfile = addentry("$queue.PostScript.$queue", - "PPD_PageSize=$papersize", $configfile); - } - # Link the PPD file - run_program::rooted($prefix, - "ln", "-sf", "/etc/foomatic/$queue.ppd", - "$configprefix/share/xp3/ppds/$queue.PS"); - return $configfile; -} - -sub makeopenofficeprinterentry { - my ($printer, $queue, $configprefix, $configfile) = @_; - # Make printer's section - $configfile = addsection($queue, $configfile); - # Load PPD file - my $ppd = cat_("$prefix/etc/foomatic/$queue.ppd"); - # "PPD_PageSize" line - if ($ppd =~ /^\s*\*DefaultPageSize:\s*(\S+)\s*$/m) { - my $papersize = $1; - $configfile = removeentry($queue, - "PPD_PageSize=", $configfile); - $configfile = addentry($queue, - "PPD_PageSize=$papersize", $configfile); - } - # "Command" line - # The "perl" command patches the PostScript output to print the Euro - # symbol correctly. - $configfile = removeentry($queue, "Command=", $configfile); - $configfile = addentry($queue, - "Command=/usr/bin/perl -p -e \"s=/euro /unused=/Euro /unused=\" | /usr/bin/$lprcommand{$printer->{SPOOLER}{print_command}} -P $queue", - $configfile); - # "Comment" line - $configfile = removeentry($queue, "Comment=", $configfile); - if (($printer->{configured}{$queue}) && - ($printer->{configured}{$queue}{queuedata}{desc})) { - $configfile = addentry - ($queue, - "Comment=$printer->{configured}{$queue}{queuedata}{desc}", - $configfile); - } else { - $configfile = addentry($queue, - "Comment=", - $configfile); - } - # "Location" line - $configfile = removeentry($queue, "Location=", $configfile); - if (($printer->{configured}{$queue}) && - ($printer->{configured}{$queue}{queuedata}{loc})) { - $configfile = addentry - ($queue, - "Location=$printer->{configured}{$queue}{queuedata}{loc}", - $configfile); - } else { - $configfile = addentry($queue, - "Location=", - $configfile); - } - # "DefaultPrinter" line - $configfile = removeentry($queue, "DefaultPrinter=", $configfile); - my $default = "0"; - if ($queue eq $printer->{DEFAULT}) { - $default = "1"; - # "DefaultPrinter=0" for the "Generic Printer" - $configfile = removeentry("Generic Printer", "DefaultPrinter=", - $configfile); - $configfile = addentry("Generic Printer", - "DefaultPrinter=0", - $configfile); - } - $configfile = addentry($queue, - "DefaultPrinter=$default", - $configfile); - # "Printer" line - $configfile = removeentry($queue, "Printer=", $configfile); - $configfile = addentry($queue, - "Printer=$queue/$queue", - $configfile); - # Link the PPD file - run_program::rooted($prefix, - "ln", "-sf", "/etc/foomatic/$queue.ppd", - "$configprefix/share/psprint/driver/$queue.PS"); - return $configfile; -} - -sub removestarofficeprinterentry { - my ($printer, $queue, $configprefix, $configfile) = @_; - # Remove default printer entry - $configfile = removeentry("windows", "device=$queue,", $configfile); - # Remove entry in the "[devices]" section - $configfile = removeentry("devices", "$queue=", $configfile); - # Remove entry in the "[ports]" section - $configfile = removeentry("ports", "$queue=", $configfile); - # Remove "[$queue,PostScript,$queue]" section - $configfile = removesection("$queue,PostScript,$queue", $configfile); - # Remove Link of PPD file - run_program::rooted($prefix, - "rm", "-f", - "$configprefix/share/xp3/ppds/$queue.PS"); - return $configfile; -} - -sub removeopenofficeprinterentry { - my ($printer, $queue, $configprefix, $configfile) = @_; - # Remove printer's section - $configfile = removesection($queue, $configfile); - # Remove Link of PPD file - run_program::rooted($prefix, - "rm", "-f", - "$configprefix/share/psprint/driver/$queue.PS"); - return $configfile; -} - -sub findsofficeconfigfile { - my @configfilenames = - ("/usr/lib/*/share/xp3/Xpdefaults", - "/usr/local/lib/*/share/xp3/Xpdefaults", - "/usr/local/*/share/xp3/Xpdefaults", - "/opt/*/share/xp3/Xpdefaults"); - foreach my $configfilename (@configfilenames) { - local *F; - if (open F, "ls -r $prefix$configfilename 2> /dev/null |") { - my $filename = <F>; - close F; - if ($filename) { - if ($prefix ne "") { - $filename =~ s/^$prefix//; - } - # Work around a bug in the "ls" of "busybox". During - # installation it outputs the mask given on the command line - # instead of nothing when the mask does not match any file - next if $filename =~ /\*/; - return $filename; - } - } - } - return ""; -} - -sub findopenofficeconfigfile { - my @configfilenames = - ("/usr/lib/*/share/psprint/psprint.conf", - "/usr/local/lib/*/share/psprint/psprint.conf", - "/usr/local/*/share/psprint/psprint.conf", - "/opt/*/share/psprint/psprint.conf"); - foreach my $configfilename (@configfilenames) { - local *F; - if (open F, "ls -r $prefix$configfilename 2> /dev/null |") { - my $filename = <F>; - close F; - if ($filename) { - if ($prefix ne "") { - $filename =~ s/^$prefix//; - } - # Work around a bug in the "ls" of "busybox". During - # installation it outputs the mask given on the command line - # instead of nothing when the mask does not match any file - next if $filename =~ /\*/; - return $filename; - } - } - } - return ""; -} - -sub readsofficeconfigfile { - my ($file) = @_; - local *F; - open F, "< $prefix$file" or return ""; - my $filecontent = join("", <F>); - close F; - return $filecontent; -} - -sub writesofficeconfigfile { - my ($file, $filecontent) = @_; - local *F; - open F, "> $prefix$file" or return 0; - print F $filecontent; - close F; - return 1; -} - -sub addentry { - my ($section, $entry, $filecontent) = @_; - my $sectionfound = 0; - my $entryinserted = 0; - my @lines = split("\n", $filecontent); - foreach (@lines) { - if (!$sectionfound) { - if (/^\s*\[\s*$section\s*\]\s*$/) { - $sectionfound = 1; - } - } else { - if (!/^\s*$/ && !/^\s*;/) { #-# - $_ = "$entry\n$_"; - $entryinserted = 1; - last; - } - } - } - if ($sectionfound && !$entryinserted) { - push(@lines, $entry); - } - return join ("\n", @lines); -} - -sub addsection { - my ($section, $filecontent) = @_; - my $entryinserted = 0; - my @lines = split("\n", $filecontent); - foreach (@lines) { - if (/^\s*\[\s*$section\s*\]\s*$/) { - # section already there, nothing to be done - return $filecontent; - } - } - return $filecontent . "\n[$section]"; -} - -sub removeentry { - my ($section, $entry, $filecontent) = @_; - my $sectionfound = 0; - my $done = 0; - my @lines = split("\n", $filecontent); - foreach (@lines) { - $_ = "$_\n"; - next if $done; - if (!$sectionfound) { - if (/^\s*\[\s*$section\s*\]\s*$/) { - $sectionfound = 1; - } - } else { - if (/^\s*\[.*\]\s*$/) { # Next section - $done = 1; - } elsif (/^\s*$entry/) { - $_ = ""; - $done = 1; - } - } - } - return join ("", @lines); -} - -sub removesection { - my ($section, $filecontent) = @_; - my $sectionfound = 0; - my $done = 0; - my @lines = split("\n", $filecontent); - foreach (@lines) { - $_ = "$_\n"; - next if $done; - if (!$sectionfound) { - if (/^\s*\[\s*$section\s*\]\s*$/) { - $_ = ""; - $sectionfound = 1; - } - } else { - if (/^\s*\[.*\]\s*$/) { # Next section - $done = 1; - } else { - $_ = ""; - } - } - } - return join ("", @lines); -} - -# ------------------------------------------------------------------ -# GIMP -# ------------------------------------------------------------------ - -sub configuregimp { - my ($printer, $queue) = @_; - # Do we have files to treat? - my @configfilenames = findgimpconfigfiles(); - return 1 if $#configfilenames < 0; - # There is no system-wide config file, treat every user's config file - foreach my $configfilename (@configfilenames) { - # Load GIMP's printer config file - my $configfilecontent = readgimpconfigfile($configfilename); - # Update local printer queues - foreach my $queue (keys(%{$printer->{configured}})) { - # Check if we have a PPD file - if (! -r "$prefix/etc/foomatic/$queue.ppd") { - if (-r "$prefix/etc/cups/ppd/$queue.ppd") { - # If we have a PPD file in the CUPS config dir, link to it - run_program::rooted($prefix, - "ln", "-sf", - "/etc/cups/ppd/$queue.ppd", - "/etc/foomatic/$queue.ppd"); - } elsif (-r "$prefix/usr/share/postscript/ppd/$queue.ppd") { - # Check PPD directory of GPR, too - run_program::rooted - ($prefix, - "ln", "-sf", - "/usr/share/postscript/ppd/$queue.ppd", - "/etc/foomatic/$queue.ppd"); - } else { - # No PPD file at all? We cannot set up this printer - next; - } - } - # Add the printer entry - if (!isgimpprinterconfigured ($queue, $configfilecontent)) { - # Remove the old printer entry - $configfilecontent = - removegimpprinter($queue, $configfilecontent); - # Add the new printer entry - $configfilecontent = - makegimpprinterentry($printer, $queue, - $configfilecontent); - } - } - # Default printer - if ($printer->{DEFAULT}) { - if ($configfilecontent !~ /^\s*Current\-Printer\s*:/m) { - $configfilecontent =~ - s/\n/\nCurrent-Printer: $printer->{DEFAULT}\n/s; - } else { - $configfilecontent =~ /^\s*Current\-Printer\s*:\s*(\S+)\s*$/m; - if (!isgimpprinterconfigured ($1, $configfilecontent)) { - $configfilecontent =~ - s/(Current\-Printer\s*:\s*)\S+/$1$printer->{DEFAULT}/; - } - } - } - # Write back GIMP's printer configuration file - writegimpconfigfile($configfilename, $configfilecontent); - } - return 1; -} - -sub addcupsremotetogimp { - my ($printer, $queue) = @_; - # Do we have files to treat? - my @configfilenames = findgimpconfigfiles(); - return 1 if $#configfilenames < 0; - my @printerlist = getcupsremotequeues(); - my $ppdfile = ""; - if (($printer->{SPOOLER} eq "cups") && - ((-x "$prefix/usr/bin/curl") || (-x "$prefix/usr/bin/wget"))) { - foreach my $listentry (@printerlist) { - next if !($listentry =~ /^([^\|]+)\|([^\|]+)$/); - my $q = $1; - next if $q ne $queue; - my $server = $2; - # Remove server name from queue name - $q =~ s/^([^@]*)@.*$/$1/; - if (-x "$prefix/usr/bin/wget") { - eval(run_program::rooted - ($prefix, "/usr/bin/wget", "-O", - "/etc/foomatic/$queue.ppd", - "http://$server:631/printers/$q.ppd")); - } else { - eval(run_program::rooted - ($prefix, "/usr/bin/curl", "-o", - "/etc/foomatic/$queue.ppd", - "http://$server:631/printers/$q.ppd")); - } - # Does the file exist and is it not an error message? - if ((-r "$prefix/etc/foomatic/$queue.ppd") && - (cat_("$prefix/etc/foomatic/$queue.ppd") =~ - /^\*PPD-Adobe/)) { - $ppdfile = "/etc/foomatic/$queue.ppd"; - } else { - unlink ("$prefix/etc/foomatic/$queue.ppd"); - return 0; - } - } - } else { - return 1; - } - # There is no system-wide config file, treat every user's config file - foreach my $configfilename (@configfilenames) { - # Load GIMP's printer config file - my $configfilecontent = readgimpconfigfile($configfilename); - # Add the printer entry - if (!isgimpprinterconfigured ($queue, $configfilecontent)) { - # Remove the old printer entry - $configfilecontent = - removegimpprinter($queue, $configfilecontent); - # Add the new printer entry - $configfilecontent = - makegimpprinterentry($printer, $queue, - $configfilecontent); - } - # Write back GIMP's printer configuration file - writegimpconfigfile($configfilename, $configfilecontent); - } - return 1; -} - -sub removeprinterfromgimp { - my ($printer, $queue) = @_; - # Do we have files to treat? - my @configfilenames = findgimpconfigfiles(); - return 1 if $#configfilenames < 0; - # There is no system-wide config file, treat every user's config file - foreach my $configfilename (@configfilenames) { - # Load GIMP's printer config file - my $configfilecontent = readgimpconfigfile($configfilename); - # Remove the printer entry - $configfilecontent = - removegimpprinter($queue, $configfilecontent); - # Write back GIMP's printer configuration file - writegimpconfigfile($configfilename, $configfilecontent); - } - return 1; -} - -sub removelocalprintersfromgimp { - my ($printer) = @_; - # Do we have files to treat? - my @configfilenames = findgimpconfigfiles(); - return 1 if $#configfilenames < 0; - # There is no system-wide config file, treat every user's config file - foreach my $configfilename (@configfilenames) { - # Load GIMP's printer config file - my $configfilecontent = readgimpconfigfile($configfilename); - # Remove the printer entries - foreach my $queue (keys(%{$printer->{configured}})) { - $configfilecontent = - removegimpprinter($queue, $configfilecontent); - } - # Write back GIMP's printer configuration file - writegimpconfigfile($configfilename, $configfilecontent); - } - return 1; -} - -sub makegimpprinterentry { - my ($printer, $queue, $configfile) = @_; - # Make printer's section - $configfile = addgimpprinter($queue, $configfile); - # Load PPD file - my $ppd = cat_("$prefix/etc/foomatic/$queue.ppd"); - # Is the printer configured with GIMP-Print? - my $gimpprintqueue = 0; - my $gimpprintdriver = "ps2"; - if ($ppd =~ /CUPS\s*\+\s*GIMP\s*\-\s*Print/im) { - # Native CUPS driver - $gimpprintqueue = 1; - $ppd =~ /\s*\*ModelName:\s*\"(\S+)\"\s*$/im; - $gimpprintdriver = $1; - } elsif ($ppd =~ /Foomatic\s*\+\s*gimp\s*\-\s*print/im) { - # GhostScript + Foomatic driver - $gimpprintqueue = 1; - $ppd =~ - /'idx'\s*=>\s*'ev\/gimp-print-((escp2|pcl|bjc|lexmark)\-\S*)'/im; - $gimpprintdriver = $1; - } - if ($gimpprintqueue) { - # Get the paper size from the PPD file - if ($ppd =~ /^\s*\*DefaultPageSize:\s*(\S+)\s*$/m) { - my $papersize = $1; - $configfile = removegimpentry($queue, - "Media-Size", $configfile); - $configfile = addgimpentry($queue, - "Media-Size: $papersize", $configfile); - } - $configfile = removegimpentry($queue, - "PPD-File:", $configfile); - $configfile = addgimpentry($queue, - "PPD-File:", $configfile); - $configfile = removegimpentry($queue, - "Driver:", $configfile); - $configfile = addgimpentry($queue, - "Driver: $gimpprintdriver", $configfile); - $configfile = removegimpentry($queue, - "Destination:", $configfile); - $configfile = addgimpentry($queue, - "Destination: /usr/bin/$lprcommand{$printer->{SPOOLER}{print_command}} -P $queue -o raw", $configfile); - } else { - $configfile = removegimpentry($queue, - "PPD-File:", $configfile); - $configfile = addgimpentry($queue, - "PPD-File: /etc/foomatic/$queue.ppd", $configfile); - $configfile = removegimpentry($queue, - "Driver:", $configfile); - $configfile = addgimpentry($queue, - "Driver: ps2", $configfile); - $configfile = removegimpentry($queue, - "Destination:", $configfile); - $configfile = addgimpentry($queue, - "Destination: /usr/bin/$lprcommand{$printer->{SPOOLER}{print_command}} -P $queue", $configfile); - } - return $configfile; -} - -sub findgimpconfigfiles { - my @configfilenames; - if (-d "$prefix/usr/lib/gimp/1.2") { - push (@configfilenames, ".gimp-1.2/printrc"); - } - if (-d "$prefix/usr/lib/gimp/1.3") { - push (@configfilenames, ".gimp-1.3/printrc"); - } - my @filestotreat; - local *PASSWD; - open PASSWD, "< $prefix/etc/passwd" or die "Cannot read /etc/passwd!\n"; - local $_; - while (<PASSWD>) { - chomp; - if (/^([^:]+):[^:]*:([^:]+):([^:]+):[^:]*:([^:]+):[^:]*$/) { - my ($username, $uid, $gid, $homedir) = ($1, $2, $3, $4); - if ((($uid == 0) || ($uid >= 500)) && ($username ne "nobody")) { - foreach my $file (@configfilenames) { - my $dir = "$homedir/$file"; - $dir =~ s,/[^/]*$,,; - next if (-f $dir) && (! -d $dir); - if (! -d "$prefix$dir") { - run_program::rooted($prefix, - "/bin/mkdir", $dir) - or next; - run_program::rooted($prefix, - "/bin/chown", "$uid.$gid", $dir) - or next; - } - if (! -f "$prefix$homedir/$file") { - local *F; - open F, "> $prefix$homedir/$file" or next; - print F "#PRINTRCv1 written by GIMP-PRINT 4.2.2 - 13 Sep 2002\n"; - close F; - run_program::rooted($prefix, - "/bin/chown", "$uid.$gid", - "$homedir/$file") - or next; - } - push (@filestotreat, "$homedir/$file"); - } - } - } - } - @filestotreat; -} - -sub readgimpconfigfile { - my ($file) = @_; - local *F; - open F, "< $prefix$file" or return ""; - my $filecontent = join("", <F>); - close F; - return $filecontent; -} - -sub writegimpconfigfile { - my ($file, $filecontent) = @_; - local *F; - open F, "> $prefix$file" or return 0; - print F $filecontent; - close F; - return 1; -} - -sub addgimpentry { - my ($section, $entry, $filecontent) = @_; - my $sectionfound = 0; - my $entryinserted = 0; - my @lines = split("\n", $filecontent); - foreach (@lines) { - if (!$sectionfound) { - if (/^\s*Printer\s*:\s*($section)\s*$/) { - $sectionfound = 1; - } - } else { - if (!/^\s*$/ && !/^\s*;/) { #-# - $_ = "$entry\n$_"; - $entryinserted = 1; - last; - } - } - } - if ($sectionfound && !$entryinserted) { - push(@lines, $entry); - } - return join ("\n", @lines); -} - -sub addgimpprinter { - my ($section, $filecontent) = @_; - my $entryinserted = 0; - my @lines = split("\n", $filecontent); - foreach (@lines) { - if (/^\s*Printer\s*:\s*($section)\s*$/) { - # section already there, nothing to be done - return $filecontent; - } - } - return $filecontent . "\nPrinter: $section"; -} - -sub removegimpentry { - my ($section, $entry, $filecontent) = @_; - my $sectionfound = 0; - my $done = 0; - my @lines = split("\n", $filecontent); - foreach (@lines) { - $_ = "$_\n"; - next if $done; - if (!$sectionfound) { - if (/^\s*Printer\s*:\s*($section)\s*$/) { - $sectionfound = 1; - } - } else { - if (/^\s*Printer\s*:\s*.*\s*$/) { # Next section - $done = 1; - } elsif (/^\s*$entry/) { - $_ = ""; - $done = 1; - } - } - } - return join ("", @lines); -} - -sub removegimpprinter { - my ($section, $filecontent) = @_; - my $sectionfound = 0; - my $done = 0; - my @lines = split("\n", $filecontent); - foreach (@lines) { - $_ = "$_\n"; - next if $done; - if (!$sectionfound) { - if (/^\s*Printer\s*:\s*($section)\s*$/) { - $_ = ""; - $sectionfound = 1; - } - } else { - if (/^\s*Printer\s*:\s*.*\s*$/) { # Next section - $done = 1; - } else { - $_ = ""; - } - } - } - return join ("", @lines); -} - -sub isgimpprinterconfigured { - my ($queue, $filecontent) = @_; - my $sectionfound = 0; - my $done = 0; - my $drivernotps2 = 0; - my $ppdfileset = 0; - my $nonrawprinting = 0; - my @lines = split("\n", $filecontent); - foreach (@lines) { - last if $done; - if (!$sectionfound) { - if (/^\s*Printer\s*:\s*($queue)\s*$/) { - $sectionfound = 1; - } - } else { - if (/^\s*Printer\s*:\s*.*\s*$/) { # Next section - $done = 1; - } elsif (/^\s*Driver:\s*(\S+)\s*$/) { - $drivernotps2 = ($1 ne "ps2"); - } elsif (/^\s*PPD\-File:\s*(\S+)\s*$/) { - $ppdfileset = 1; - } elsif (/^\s*Destination:\s*(\S+.*)$/) { - $nonrawprinting = ($1 !~ /\-o\s*raw/); - } - } - } - return 0 if $done && !$sectionfound; - return 1 if $ppdfileset || $drivernotps2 || $nonrawprinting; - return 0; -} - -# ------------------------------------------------------------------ - -1; |