#!/usr/perl5/bin/perl # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # # # This program manages the "active" print service selection. # If called as 'print-service', it takes one of four options. # Options: # [-s[et] service [-m]] Select the "active" print service, optionally # migrating basic print queue configuration. # [-q[uery]] Display the "active" print service. # [-e[xport] file] Export basic print queue configuration to # a file. # [-i[mport] file] Import basic print queue configuration from # a file. # # If called by any other name, it will look for a corresponding command # under /usr/lib/{active-service}/bin/{command} and execute that program # with the original arguments. # use Getopt::Long; use File::Basename; use File::Copy; use File::Temp qw/ :POSIX /; my $cmd = basename($0); my $LPSTAT = '/usr/bin/lpstat'; my $LPADMIN = '/usr/sbin/lpadmin'; my $ENABLE = '/usr/bin/enable'; my $ACCEPT = '/usr/sbin/accept'; my $SVCADM = '/usr/sbin/svcadm'; my $SVCPROP = '/usr/bin/svcprop'; my $SVCCFG = '/usr/sbin/svccfg'; my $SVC_LP_SCHEDULER = 'print/server'; my $SVC_LP_LPD = 'print/rfc1179'; my $SVC_LP_IPP = 'print/ipp-listener'; my $SVC_LP_PPD = 'print/ppd-cache-update'; my $SVC_CUPS_SCHEDULER = 'cups/scheduler'; my $SVC_CUPS_LPD = 'cups/in-lpd'; sub fatal { ($ENV{"DESKTOP_LAUNCHED"}) && exec("/bin/zenity", "--error", "--text=@_"); print STDERR @_; exit(1); } sub usage { print STDERR </dev/null |"); $result = <$FH>; close($FH); return ($result); } sub svccfg { local ($fmri, $operation) = @_; my $FH; open($FH, "$SVCCFG -s $fmri \"$operation\" 2>/dev/null |"); $result = <$FH>; close($FH); return ($result); } sub svcadm { local ($operation, @fmris) = @_; system("$SVCADM $operation -s @fmris"); } sub print_service { my $service; $service = svcprop("$SVC_CUPS_SCHEDULER:default", "general/active"); ($service =~ /true/) && ($service = 'cups') || ($service = 'lp'); return ($service); } sub print_command { local($command, @av) = @_; my $service = print_service(); if (!defined($service)) { fatal("failed to detect active print service: $!\n"); } if (! -d "/usr/lib/$service/bin") { fatal("print service: $service is not installed\n"); } my $executable = "/usr/lib/$service/bin/$command"; # CUPS has it's own names for enable and disable ($command =~ /(en|dis)able/) && ($service eq 'cups') && (! -x $executable) && ($executable = "/usr/lib/$service/bin/$service$command"); if (! -x $executable) { fatal("$command is not available from $service print service\n"); } exec($executable, @ARGV); } sub export_print_queues { local ($path) = @_; my $service = print_service(); if ($service eq 'lp') { my $FH, $DFH; open($FH, ">$path"); open($DFH, "$LPSTAT -v|"); while (<$DFH>) { if (/device for (.+): (.+)/) { my $EFH; print $FH "\nDeviceURI $2\n"; open($EFH, "$LPSTAT -p $1 -l |"); while (<$EFH>) { (/Description: (.+)/) && print $FH "Info $1\n"; } close($EFH); print $FH "\n"; } } close($DFH); close($FH); } else { copy('/etc/cups/printers.conf', $path); } } sub psystem { print " @_\n"; system(@_); } sub import_print_queues { local ($path) = @_; my $service = print_service(); my $FH, %printer, @options; # store queue info in the 'active' print service open($FH, "<$path"); while (<$FH>) { if (//) { $printer{'Printer'} = $1; @options = (); push(@options, "-p", $1); } elsif (/([^\s]+)\s(.+)/) { $printer{$1} = $2; my $value = $2; ($1 eq 'DeviceURI') && push(@options, "-v", $value); ($1 eq 'Info') && push(@options, "-D", $value); } elsif (/<\/Printer>/) { ($service eq 'lp') && push(@options, "-m", "uri"); print "importing $printer{'Printer'}...\n"; # create a queue psystem($LPADMIN, @options); psystem($ENABLE, $printer{'Printer'}); ($printer{'Accepting'} eq 'Yes') && psystem($ACCEPT, $printer{'Printer'}); $printer = (); } } close($FH); } sub select_service { my ($service, $migrate) = @_; my $FH, $queues; if (! -d "/usr/lib/$service/bin") { fatal("print service: $service is not installed\n"); } if ($migrate == 1) { # export old print queue configuration (if migrating) $queues = tmpnam(); export_print_queues($queues); } # enable/disable the services if ($service eq 'cups') { (-f '/etc/printers.conf') && (! -f '/etc/lp/printers.conf') && rename('/etc/printers.conf', '/etc/lp/printers.conf'); print("disabling LP services...\n"); svcadm("disable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD, $SVC_LP_PPD); print("enabling CUPS services...\n"); svcadm("enable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD); svccfg("cups/scheduler:default", "setprop general/active = boolean: true"); system("pkill -USR1 -f '/desktop-print-management-applet'"); } else { print("disabling CUPS services...\n"); svcadm("disable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD); print("enabling LP services...\n"); svcadm("enable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD, $SVC_LP_PPD); (-f '/etc/lp/printers.conf') && rename('/etc/lp/printers.conf', '/etc/printers.conf'); svccfg("cups/scheduler:default", "delprop general/active"); system("pkill -USR1 -f '/desktop-print-management-applet'"); } # import the new print queue configuration (if migrating) defined($queues) && import_print_queues($queues); } sub query_service { my $service = print_service(); if (!defined($service)) { fatal("failed to detect active print service: $!\n"); } print "active print service: $service\n"; } if ($cmd eq 'print-service') { my ($import_path, $export_path, $svc_name, $query, $migrate) = (); my $res = GetOptions('q|query' => \$query, 's|set=s' => \$service, 'm|migrate' => \$migrate, 'e|export=s' => \$export_path, 'i|import=s' => \$import_path); ($res) || usage(); if (defined($import_path) && !defined($export_path) && !defined($query) && !defined($service) && !defined($migrate)) { import_print_queues($import_path); } elsif (!defined($import_path) && defined($export_path) && !defined($query) && !defined($service) && !defined($migrate)) { export_print_queues($export_path); } elsif (!defined($import_path) && !defined($export_path) && defined($query) && !defined($service) && !defined($migrate)) { query_service(); } elsif (!defined($import_path) && !defined($export_path) && !defined($query) && defined($service)) { select_service($service, $migrate); } else { usage(); } } else { print_command($cmd, @ARGV); } exit(0);