893N/A#!/usr/perl5/bin/perl
2362N/A#
893N/A# CDDL HEADER START
893N/A#
893N/A# The contents of this file are subject to the terms of the
893N/A# Common Development and Distribution License (the "License").
893N/A# You may not use this file except in compliance with the License.
893N/A#
893N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
893N/A# or http://www.opensolaris.org/os/licensing.
893N/A# See the License for the specific language governing permissions
893N/A# and limitations under the License.
893N/A#
893N/A# When distributing Covered Code, include this CDDL HEADER in each
893N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
893N/A# If applicable, add the following below this CDDL HEADER, with the
893N/A# fields enclosed by brackets "[]" replaced with your own identifying
893N/A# information: Portions Copyright [yyyy] [name of copyright owner]
2362N/A#
2362N/A# CDDL HEADER END
2362N/A#
893N/A# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
893N/A# Use is subject to license terms.
893N/A#
1319N/A#
893N/A
893N/A#
893N/A# This program manages the "active" print service selection.
893N/A# If called as 'print-service', it takes one of four options.
893N/A# Options:
893N/A# [-s[et] service [-m]] Select the "active" print service, optionally
893N/A# migrating basic print queue configuration.
893N/A# [-q[uery]] Display the "active" print service.
893N/A# [-e[xport] file] Export basic print queue configuration to
893N/A# a file.
893N/A# [-i[mport] file] Import basic print queue configuration from
893N/A# a file.
893N/A#
893N/A# If called by any other name, it will look for a corresponding command
893N/A# under /usr/lib/{active-service}/bin/{command} and execute that program
893N/A# with the original arguments.
893N/A#
893N/A
893N/Ause Getopt::Long;
893N/Ause File::Basename;
893N/Ause File::Copy;
893N/Ause File::Temp qw/ :POSIX /;
893N/A
893N/Amy $cmd = basename($0);
893N/A
893N/Amy $LPSTAT = '/usr/bin/lpstat';
893N/Amy $LPADMIN = '/usr/sbin/lpadmin';
893N/Amy $ENABLE = '/usr/bin/enable';
893N/Amy $ACCEPT = '/usr/sbin/accept';
893N/Amy $SVCADM = '/usr/sbin/svcadm';
893N/Amy $SVCPROP = '/usr/bin/svcprop';
893N/Amy $SVCCFG = '/usr/sbin/svccfg';
893N/Amy $SVC_LP_SCHEDULER = 'print/server';
893N/Amy $SVC_LP_LPD = 'print/rfc1179';
893N/Amy $SVC_LP_IPP = 'print/ipp-listener';
893N/Amy $SVC_LP_PPD = 'print/ppd-cache-update';
893N/Amy $SVC_CUPS_SCHEDULER = 'cups/scheduler';
893N/Amy $SVC_CUPS_LPD = 'cups/in-lpd';
893N/A
3471N/Asub fatal {
893N/A ($ENV{"DESKTOP_LAUNCHED"}) &&
893N/A exec("/bin/zenity", "--error", "--text=@_");
893N/A print STDERR @_;
893N/A exit(1);
893N/A}
893N/A
893N/Asub usage {
3471N/A print STDERR <<EOF ;
893N/AUsage:
893N/A $cmd [-s[et] service [-m]] Select the \"active\" print service,
893N/A optionally migrating basic print queue
893N/A configuration.
893N/A $cmd [-q[uery]] Display the "active" print service.
893N/A $cmd [-e[xport] file] Export basic print queue configuration
893N/A to a file.
893N/A $cmd [-i[mport] file] Import basic print queue configuration
893N/A from a file.
893N/AEOF
893N/A exit(1);
3471N/A}
893N/A
893N/Asub svcprop {
893N/A local ($fmri, $property) = @_;
893N/A my $FH;
893N/A
893N/A open($FH, "$SVCPROP -C -p $property $fmri 2>/dev/null |");
893N/A $result = <$FH>;
893N/A close($FH);
893N/A
893N/A return ($result);
3471N/A}
893N/A
893N/Asub svccfg {
3471N/A local ($fmri, $operation) = @_;
893N/A my $FH;
3471N/A
893N/A open($FH, "$SVCCFG -s $fmri \"$operation\" 2>/dev/null |");
893N/A $result = <$FH>;
893N/A close($FH);
3471N/A
893N/A return ($result);
893N/A}
893N/A
3471N/Asub svcadm {
893N/A local ($operation, @fmris) = @_;
893N/A
893N/A system("$SVCADM $operation -s @fmris");
893N/A}
893N/A
893N/A
893N/Asub print_service {
893N/A my $service;
893N/A
893N/A $service = svcprop("$SVC_CUPS_SCHEDULER:default", "general/active");
893N/A ($service =~ /true/) && ($service = 'cups') || ($service = 'lp');
893N/A
3471N/A return ($service);
893N/A}
893N/A
893N/Asub print_command {
893N/A local($command, @av) = @_;
893N/A my $service = print_service();
893N/A
893N/A if (!defined($service)) {
893N/A fatal("failed to detect active print service: $!\n");
893N/A }
893N/A
893N/A if (! -d "/usr/lib/$service/bin") {
893N/A fatal("print service: $service is not installed\n");
893N/A }
893N/A
893N/A my $executable = "/usr/lib/$service/bin/$command";
893N/A # CUPS has it's own names for enable and disable
893N/A ($command =~ /(en|dis)able/) && ($service eq 'cups') &&
893N/A (! -x $executable) &&
893N/A ($executable = "/usr/lib/$service/bin/$service$command");
893N/A
893N/A 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 "<Printer $1>\nDeviceURI $2\n";
open($EFH, "$LPSTAT -p $1 -l |");
while (<$EFH>) {
(/Description: (.+)/) &&
print $FH "Info $1\n";
}
close($EFH);
print $FH "</Printer>\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{'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);