16237Sjacobs#!/usr/perl5/bin/perl
26237Sjacobs#
36237Sjacobs# CDDL HEADER START
46237Sjacobs#
56237Sjacobs# The contents of this file are subject to the terms of the
66237Sjacobs# Common Development and Distribution License (the "License").
76237Sjacobs# You may not use this file except in compliance with the License.
86237Sjacobs#
96237Sjacobs# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
106237Sjacobs# or http://www.opensolaris.org/os/licensing.
116237Sjacobs# See the License for the specific language governing permissions
126237Sjacobs# and limitations under the License.
136237Sjacobs#
146237Sjacobs# When distributing Covered Code, include this CDDL HEADER in each
156237Sjacobs# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
166237Sjacobs# If applicable, add the following below this CDDL HEADER, with the
176237Sjacobs# fields enclosed by brackets "[]" replaced with your own identifying
186237Sjacobs# information: Portions Copyright [yyyy] [name of copyright owner]
196237Sjacobs#
206237Sjacobs# CDDL HEADER END
216237Sjacobs#
226237Sjacobs# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
236237Sjacobs# Use is subject to license terms.
246237Sjacobs#
256237Sjacobs# ident	"%Z%%M%	%I%	%E% SMI"
266237Sjacobs#
276237Sjacobs
286237Sjacobs#
296237Sjacobs# This program manages the "active" print service selection.
306237Sjacobs#   If called as 'print-service', it takes one of four options.
316237Sjacobs#   Options:
326237Sjacobs#     [-s[et] service [-m]]	Select the "active" print service, optionally
336237Sjacobs#				migrating basic print queue configuration.
346237Sjacobs#     [-q[uery]]		Display the "active" print service.
356237Sjacobs#     [-e[xport] file]		Export basic print queue configuration to
366237Sjacobs#				a file.
376237Sjacobs#     [-i[mport] file]		Import basic print queue configuration from
386237Sjacobs#				a file.
396237Sjacobs#
406237Sjacobs#   If called by any other name, it will look for a corresponding command
416237Sjacobs#   under /usr/lib/{active-service}/bin/{command} and execute that program
426237Sjacobs#   with the original arguments.
436237Sjacobs#
446237Sjacobs
456237Sjacobsuse Getopt::Long;
466237Sjacobsuse File::Basename;
476237Sjacobsuse File::Copy;
486237Sjacobsuse File::Temp qw/ :POSIX /;
496237Sjacobs
506237Sjacobsmy $cmd = basename($0);
516237Sjacobs
526237Sjacobsmy $LPSTAT = '/usr/bin/lpstat';
536237Sjacobsmy $LPADMIN = '/usr/sbin/lpadmin';
546237Sjacobsmy $ENABLE = '/usr/bin/enable';
556237Sjacobsmy $ACCEPT = '/usr/sbin/accept';
566237Sjacobsmy $SVCADM = '/usr/sbin/svcadm';
576237Sjacobsmy $SVCPROP = '/usr/bin/svcprop';
586237Sjacobsmy $SVCCFG = '/usr/sbin/svccfg';
596237Sjacobsmy $SVC_LP_SCHEDULER = 'print/server';
606237Sjacobsmy $SVC_LP_LPD = 'print/rfc1179';
616237Sjacobsmy $SVC_LP_IPP = 'print/ipp-listener';
62*6817Sjacobsmy $SVC_LP_PPD = 'print/ppd-cache-update';
636237Sjacobsmy $SVC_CUPS_SCHEDULER = 'cups/scheduler';
646237Sjacobsmy $SVC_CUPS_LPD = 'cups/in-lpd';
656237Sjacobs
666237Sjacobssub fatal {
676237Sjacobs	print STDERR @_;
686237Sjacobs	exit(1);
696237Sjacobs}
706237Sjacobs
716237Sjacobssub usage {
726237Sjacobs	print STDERR <<EOF ;
736237SjacobsUsage:
746237Sjacobs  $cmd [-s[et] service [-m]]	Select the \"active\" print service,
756237Sjacobs					optionally migrating basic print queue
766237Sjacobs					configuration.
776237Sjacobs  $cmd [-q[uery]]		Display the "active" print service.
786237Sjacobs  $cmd [-e[xport] file]	Export basic print queue configuration
796237Sjacobs					to a file.
806237Sjacobs  $cmd [-i[mport] file]	Import basic print queue configuration
816237Sjacobs					from a file.
826237SjacobsEOF
836237Sjacobs	exit(1);
846237Sjacobs}
856237Sjacobs
866237Sjacobssub svcprop {
876237Sjacobs	local ($fmri, $property) = @_;
886237Sjacobs	my $FH;
896237Sjacobs
906237Sjacobs	open($FH, "$SVCPROP -C -p $property $fmri 2>/dev/null |");
916237Sjacobs	$result = <$FH>;
926237Sjacobs	close($FH);
936237Sjacobs
946237Sjacobs	return ($result);
956237Sjacobs}
966237Sjacobs
976237Sjacobssub svccfg {
986237Sjacobs	local ($fmri, $operation) = @_;
996237Sjacobs	my $FH;
1006237Sjacobs
1016237Sjacobs	open($FH, "$SVCCFG -s $fmri \"$operation\" 2>/dev/null |");
1026237Sjacobs	$result = <$FH>;
1036237Sjacobs	close($FH);
1046237Sjacobs
1056237Sjacobs	return ($result);
1066237Sjacobs}
1076237Sjacobs
1086237Sjacobssub svcadm {
1096237Sjacobs	local ($operation, @fmris) = @_;
1106237Sjacobs
1116237Sjacobs	system("$SVCADM $operation -s @fmris");
1126237Sjacobs}
1136237Sjacobs
1146237Sjacobs
1156237Sjacobssub print_service {
1166237Sjacobs	my $service;
1176237Sjacobs
1186237Sjacobs	$service = svcprop("$SVC_CUPS_SCHEDULER:default", "general/active");
1196237Sjacobs	($service =~ /true/) && ($service = 'cups') || ($service = 'lp');
1206237Sjacobs
1216237Sjacobs	return ($service);
1226237Sjacobs}
1236237Sjacobs
1246237Sjacobssub print_command {
1256237Sjacobs	local($command, @av) = @_;
1266237Sjacobs	my $service = print_service();
1276237Sjacobs
1286237Sjacobs	if (!defined($service)) {
1296237Sjacobs		fatal("failed to detect active print service: $!\n");
1306237Sjacobs	}
1316237Sjacobs
1326237Sjacobs	if (! -d "/usr/lib/$service/bin") {
1336237Sjacobs		fatal("print service: $service is not installed\n");
1346237Sjacobs	}
1356237Sjacobs
1366237Sjacobs	my $executable = "/usr/lib/$service/bin/$command";
1376237Sjacobs	# CUPS has it's own names for enable and disable
1386237Sjacobs	($command =~ /(en|dis)able/) && ($service eq 'cups') &&
1396237Sjacobs		(! -x $executable) &&
1406237Sjacobs		($executable = "/usr/lib/$service/bin/$service$command");
1416237Sjacobs
1426237Sjacobs	if (! -x $executable) {
1436237Sjacobs		fatal("$command is not available from $service print service\n");
1446237Sjacobs	}
1456237Sjacobs
1466237Sjacobs	exec($executable, @ARGV);
1476237Sjacobs}
1486237Sjacobs
1496237Sjacobssub export_print_queues {
1506237Sjacobs	local ($path) = @_;
1516237Sjacobs	my $service = print_service();
1526237Sjacobs
1536237Sjacobs	if ($service eq 'lp') {
1546237Sjacobs		my $FH, $DFH;
1556237Sjacobs
1566237Sjacobs		open($FH, ">$path");
1576237Sjacobs		open($DFH, "$LPSTAT -v|");
1586237Sjacobs		while (<$DFH>) {
1596237Sjacobs			if (/device for (.+): (.+)/) {
1606237Sjacobs				my $EFH;
1616237Sjacobs
1626237Sjacobs				print $FH "<Printer $1>\nDeviceURI $2\n";
1636237Sjacobs				open($EFH, "$LPSTAT -p $1 -l |");
1646237Sjacobs				while (<$EFH>) {
1656237Sjacobs					(/Description: (.+)/) &&
1666237Sjacobs						print $FH "Info $1\n";
1676237Sjacobs				}
1686237Sjacobs				close($EFH);
1696237Sjacobs				print $FH "</Printer>\n";
1706237Sjacobs			}
1716237Sjacobs		}
1726237Sjacobs		close($DFH);
1736237Sjacobs		close($FH);
1746237Sjacobs	} else {
1756237Sjacobs		copy('/etc/cups/printers.conf', $path);
1766237Sjacobs	}
1776237Sjacobs}
1786237Sjacobs
1796237Sjacobssub psystem {
1806237Sjacobs	print "  @_\n";
1816237Sjacobs	system(@_);
1826237Sjacobs}
1836237Sjacobs
1846237Sjacobssub import_print_queues {
1856237Sjacobs	local ($path) = @_;
1866237Sjacobs	my $service = print_service();
1876237Sjacobs	my $FH, %printer, @options;
1886237Sjacobs
1896237Sjacobs	# store queue info in the 'active' print service
1906237Sjacobs	open($FH, "<$path");
1916237Sjacobs	while (<$FH>) {
1926237Sjacobs		if (/<Printer (.+)>/) {
1936237Sjacobs			$printer{'Printer'} = $1;
1946237Sjacobs			@options = ();
1956237Sjacobs			push(@options, "-p", $1);
1966237Sjacobs		} elsif (/([^\s]+)\s(.+)/) {
1976237Sjacobs			$printer{$1} = $2;
1986237Sjacobs			my $value = $2;
1996237Sjacobs			($1 eq 'DeviceURI') &&
2006237Sjacobs				push(@options, "-v", $value);
2016237Sjacobs			($1 eq 'Info') &&
2026237Sjacobs				push(@options, "-D", $value);
2036237Sjacobs		} elsif (/<\/Printer>/) {
2046237Sjacobs			($service eq 'lp') &&
2056237Sjacobs				push(@options, "-m", "uri");
2066237Sjacobs			print "importing $printer{'Printer'}...\n";
2076237Sjacobs			# create a queue
2086237Sjacobs			psystem($LPADMIN, @options);
2096237Sjacobs			psystem($ENABLE, $printer{'Printer'});
2106237Sjacobs			($printer{'Accepting'} eq 'Yes') &&
2116237Sjacobs				psystem($ACCEPT, $printer{'Printer'});
2126237Sjacobs			$printer = ();
2136237Sjacobs		}
2146237Sjacobs	}
2156237Sjacobs	close($FH);
2166237Sjacobs}
2176237Sjacobs
2186237Sjacobssub select_service {
2196237Sjacobs	my ($service, $migrate) = @_;
2206237Sjacobs	my $FH, $queues;
2216237Sjacobs
2226237Sjacobs	if (! -d "/usr/lib/$service/bin") {
2236237Sjacobs		fatal("print service: $service is not installed\n");
2246237Sjacobs	}
2256237Sjacobs
2266237Sjacobs	if ($migrate == 1) {
2276237Sjacobs		# export old print queue configuration (if migrating)
2286237Sjacobs		$queues = tmpnam();
2296237Sjacobs		export_print_queues($queues);
2306237Sjacobs	}
2316237Sjacobs
2326237Sjacobs	# enable/disable the services
2336237Sjacobs	if ($service eq 'cups') {
234*6817Sjacobs		(-f '/etc/printers.conf') && (! -f '/etc/lp/printers.conf') &&
235*6817Sjacobs			rename('/etc/printers.conf', '/etc/lp/printers.conf');
2366237Sjacobs		print("disabling LP services...\n");
237*6817Sjacobs		svcadm("disable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD,
238*6817Sjacobs				  $SVC_LP_PPD);
2396237Sjacobs		print("enabling CUPS services...\n");
2406237Sjacobs		svcadm("enable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD);
2416237Sjacobs		svccfg("cups/scheduler:default",
2426237Sjacobs			"setprop general/active = boolean: true");
2436237Sjacobs	} else {
2446237Sjacobs		print("disabling CUPS services...\n");
2456237Sjacobs		svcadm("disable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD);
2466237Sjacobs		print("enabling LP services...\n");
247*6817Sjacobs		svcadm("enable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD,
248*6817Sjacobs				  $SVC_LP_PPD);
249*6817Sjacobs		(-f '/etc/lp/printers.conf') &&
250*6817Sjacobs			rename('/etc/lp/printers.conf', '/etc/printers.conf');
2516237Sjacobs		svccfg("cups/scheduler:default", "delprop general/active");
2526237Sjacobs	}
2536237Sjacobs
2546237Sjacobs	# import the new print queue configuration (if migrating)
2556237Sjacobs	defined($queues) && import_print_queues($queues);
2566237Sjacobs}
2576237Sjacobs
2586237Sjacobssub query_service {
2596237Sjacobs	my $service = print_service();
2606237Sjacobs
2616237Sjacobs	if (!defined($service)) {
2626237Sjacobs		fatal("failed to detect active print service: $!\n");
2636237Sjacobs	}
2646237Sjacobs	print "active print service: $service\n";
2656237Sjacobs}
2666237Sjacobs
2676237Sjacobsif ($cmd eq 'print-service') {
2686237Sjacobs	my ($import_path, $export_path, $svc_name, $query, $migrate) = ();
2696237Sjacobs
2706237Sjacobs	my $res = GetOptions('q|query' => \$query, 's|set=s' => \$service,
2716237Sjacobs		'm|migrate' => \$migrate, 'e|export=s' => \$export_path,
2726237Sjacobs		'i|import=s' => \$import_path);
2736237Sjacobs
2746237Sjacobs	($res) || usage();
2756237Sjacobs
2766237Sjacobs	if (defined($import_path) && !defined($export_path) &&
2776237Sjacobs	    !defined($query) && !defined($service) && !defined($migrate)) {
2786237Sjacobs		import_print_queues($import_path);
2796237Sjacobs	} elsif (!defined($import_path) && defined($export_path) &&
2806237Sjacobs		 !defined($query) && !defined($service) && !defined($migrate)) {
2816237Sjacobs		export_print_queues($export_path);
2826237Sjacobs	} elsif (!defined($import_path) && !defined($export_path) &&
2836237Sjacobs		 defined($query) && !defined($service) && !defined($migrate)) {
2846237Sjacobs		query_service();
2856237Sjacobs	} elsif (!defined($import_path) && !defined($export_path) &&
2866237Sjacobs		 !defined($query) && defined($service)) {
2876237Sjacobs		select_service($service, $migrate);
2886237Sjacobs	} else {
2896237Sjacobs		usage();
2906237Sjacobs	}
2916237Sjacobs} else {
2926237Sjacobs	print_command($cmd, @ARGV);
2936237Sjacobs}
2946237Sjacobs
2956237Sjacobsexit(0);
296