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';
626817Sjacobsmy $SVC_LP_PPD = 'print/ppd-cache-update';
636237Sjacobsmy $SVC_CUPS_SCHEDULER = 'cups/scheduler';
646237Sjacobsmy $SVC_CUPS_LPD = 'cups/in-lpd';
656237Sjacobs
666237Sjacobssub fatal {
67*7253Sjacobs	($ENV{"DESKTOP_LAUNCHED"}) &&
68*7253Sjacobs		exec("/bin/zenity", "--error", "--text=@_");
696237Sjacobs	print STDERR @_;
706237Sjacobs	exit(1);
716237Sjacobs}
726237Sjacobs
736237Sjacobssub usage {
746237Sjacobs	print STDERR <<EOF ;
756237SjacobsUsage:
766237Sjacobs  $cmd [-s[et] service [-m]]	Select the \"active\" print service,
776237Sjacobs					optionally migrating basic print queue
786237Sjacobs					configuration.
796237Sjacobs  $cmd [-q[uery]]		Display the "active" print service.
806237Sjacobs  $cmd [-e[xport] file]	Export basic print queue configuration
816237Sjacobs					to a file.
826237Sjacobs  $cmd [-i[mport] file]	Import basic print queue configuration
836237Sjacobs					from a file.
846237SjacobsEOF
856237Sjacobs	exit(1);
866237Sjacobs}
876237Sjacobs
886237Sjacobssub svcprop {
896237Sjacobs	local ($fmri, $property) = @_;
906237Sjacobs	my $FH;
916237Sjacobs
926237Sjacobs	open($FH, "$SVCPROP -C -p $property $fmri 2>/dev/null |");
936237Sjacobs	$result = <$FH>;
946237Sjacobs	close($FH);
956237Sjacobs
966237Sjacobs	return ($result);
976237Sjacobs}
986237Sjacobs
996237Sjacobssub svccfg {
1006237Sjacobs	local ($fmri, $operation) = @_;
1016237Sjacobs	my $FH;
1026237Sjacobs
1036237Sjacobs	open($FH, "$SVCCFG -s $fmri \"$operation\" 2>/dev/null |");
1046237Sjacobs	$result = <$FH>;
1056237Sjacobs	close($FH);
1066237Sjacobs
1076237Sjacobs	return ($result);
1086237Sjacobs}
1096237Sjacobs
1106237Sjacobssub svcadm {
1116237Sjacobs	local ($operation, @fmris) = @_;
1126237Sjacobs
1136237Sjacobs	system("$SVCADM $operation -s @fmris");
1146237Sjacobs}
1156237Sjacobs
1166237Sjacobs
1176237Sjacobssub print_service {
1186237Sjacobs	my $service;
1196237Sjacobs
1206237Sjacobs	$service = svcprop("$SVC_CUPS_SCHEDULER:default", "general/active");
1216237Sjacobs	($service =~ /true/) && ($service = 'cups') || ($service = 'lp');
1226237Sjacobs
1236237Sjacobs	return ($service);
1246237Sjacobs}
1256237Sjacobs
1266237Sjacobssub print_command {
1276237Sjacobs	local($command, @av) = @_;
1286237Sjacobs	my $service = print_service();
1296237Sjacobs
1306237Sjacobs	if (!defined($service)) {
1316237Sjacobs		fatal("failed to detect active print service: $!\n");
1326237Sjacobs	}
1336237Sjacobs
1346237Sjacobs	if (! -d "/usr/lib/$service/bin") {
1356237Sjacobs		fatal("print service: $service is not installed\n");
1366237Sjacobs	}
1376237Sjacobs
1386237Sjacobs	my $executable = "/usr/lib/$service/bin/$command";
1396237Sjacobs	# CUPS has it's own names for enable and disable
1406237Sjacobs	($command =~ /(en|dis)able/) && ($service eq 'cups') &&
1416237Sjacobs		(! -x $executable) &&
1426237Sjacobs		($executable = "/usr/lib/$service/bin/$service$command");
1436237Sjacobs
1446237Sjacobs	if (! -x $executable) {
1456237Sjacobs		fatal("$command is not available from $service print service\n");
1466237Sjacobs	}
1476237Sjacobs
1486237Sjacobs	exec($executable, @ARGV);
1496237Sjacobs}
1506237Sjacobs
1516237Sjacobssub export_print_queues {
1526237Sjacobs	local ($path) = @_;
1536237Sjacobs	my $service = print_service();
1546237Sjacobs
1556237Sjacobs	if ($service eq 'lp') {
1566237Sjacobs		my $FH, $DFH;
1576237Sjacobs
1586237Sjacobs		open($FH, ">$path");
1596237Sjacobs		open($DFH, "$LPSTAT -v|");
1606237Sjacobs		while (<$DFH>) {
1616237Sjacobs			if (/device for (.+): (.+)/) {
1626237Sjacobs				my $EFH;
1636237Sjacobs
1646237Sjacobs				print $FH "<Printer $1>\nDeviceURI $2\n";
1656237Sjacobs				open($EFH, "$LPSTAT -p $1 -l |");
1666237Sjacobs				while (<$EFH>) {
1676237Sjacobs					(/Description: (.+)/) &&
1686237Sjacobs						print $FH "Info $1\n";
1696237Sjacobs				}
1706237Sjacobs				close($EFH);
1716237Sjacobs				print $FH "</Printer>\n";
1726237Sjacobs			}
1736237Sjacobs		}
1746237Sjacobs		close($DFH);
1756237Sjacobs		close($FH);
1766237Sjacobs	} else {
1776237Sjacobs		copy('/etc/cups/printers.conf', $path);
1786237Sjacobs	}
1796237Sjacobs}
1806237Sjacobs
1816237Sjacobssub psystem {
1826237Sjacobs	print "  @_\n";
1836237Sjacobs	system(@_);
1846237Sjacobs}
1856237Sjacobs
1866237Sjacobssub import_print_queues {
1876237Sjacobs	local ($path) = @_;
1886237Sjacobs	my $service = print_service();
1896237Sjacobs	my $FH, %printer, @options;
1906237Sjacobs
1916237Sjacobs	# store queue info in the 'active' print service
1926237Sjacobs	open($FH, "<$path");
1936237Sjacobs	while (<$FH>) {
1946237Sjacobs		if (/<Printer (.+)>/) {
1956237Sjacobs			$printer{'Printer'} = $1;
1966237Sjacobs			@options = ();
1976237Sjacobs			push(@options, "-p", $1);
1986237Sjacobs		} elsif (/([^\s]+)\s(.+)/) {
1996237Sjacobs			$printer{$1} = $2;
2006237Sjacobs			my $value = $2;
2016237Sjacobs			($1 eq 'DeviceURI') &&
2026237Sjacobs				push(@options, "-v", $value);
2036237Sjacobs			($1 eq 'Info') &&
2046237Sjacobs				push(@options, "-D", $value);
2056237Sjacobs		} elsif (/<\/Printer>/) {
2066237Sjacobs			($service eq 'lp') &&
2076237Sjacobs				push(@options, "-m", "uri");
2086237Sjacobs			print "importing $printer{'Printer'}...\n";
2096237Sjacobs			# create a queue
2106237Sjacobs			psystem($LPADMIN, @options);
2116237Sjacobs			psystem($ENABLE, $printer{'Printer'});
2126237Sjacobs			($printer{'Accepting'} eq 'Yes') &&
2136237Sjacobs				psystem($ACCEPT, $printer{'Printer'});
2146237Sjacobs			$printer = ();
2156237Sjacobs		}
2166237Sjacobs	}
2176237Sjacobs	close($FH);
2186237Sjacobs}
2196237Sjacobs
2206237Sjacobssub select_service {
2216237Sjacobs	my ($service, $migrate) = @_;
2226237Sjacobs	my $FH, $queues;
2236237Sjacobs
2246237Sjacobs	if (! -d "/usr/lib/$service/bin") {
2256237Sjacobs		fatal("print service: $service is not installed\n");
2266237Sjacobs	}
2276237Sjacobs
2286237Sjacobs	if ($migrate == 1) {
2296237Sjacobs		# export old print queue configuration (if migrating)
2306237Sjacobs		$queues = tmpnam();
2316237Sjacobs		export_print_queues($queues);
2326237Sjacobs	}
2336237Sjacobs
2346237Sjacobs	# enable/disable the services
2356237Sjacobs	if ($service eq 'cups') {
2366817Sjacobs		(-f '/etc/printers.conf') && (! -f '/etc/lp/printers.conf') &&
2376817Sjacobs			rename('/etc/printers.conf', '/etc/lp/printers.conf');
2386237Sjacobs		print("disabling LP services...\n");
2396817Sjacobs		svcadm("disable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD,
2406817Sjacobs				  $SVC_LP_PPD);
2416237Sjacobs		print("enabling CUPS services...\n");
2426237Sjacobs		svcadm("enable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD);
2436237Sjacobs		svccfg("cups/scheduler:default",
2446237Sjacobs			"setprop general/active = boolean: true");
2456237Sjacobs	} else {
2466237Sjacobs		print("disabling CUPS services...\n");
2476237Sjacobs		svcadm("disable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD);
2486237Sjacobs		print("enabling LP services...\n");
2496817Sjacobs		svcadm("enable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD,
2506817Sjacobs				  $SVC_LP_PPD);
2516817Sjacobs		(-f '/etc/lp/printers.conf') &&
2526817Sjacobs			rename('/etc/lp/printers.conf', '/etc/printers.conf');
2536237Sjacobs		svccfg("cups/scheduler:default", "delprop general/active");
2546237Sjacobs	}
2556237Sjacobs
2566237Sjacobs	# import the new print queue configuration (if migrating)
2576237Sjacobs	defined($queues) && import_print_queues($queues);
2586237Sjacobs}
2596237Sjacobs
2606237Sjacobssub query_service {
2616237Sjacobs	my $service = print_service();
2626237Sjacobs
2636237Sjacobs	if (!defined($service)) {
2646237Sjacobs		fatal("failed to detect active print service: $!\n");
2656237Sjacobs	}
2666237Sjacobs	print "active print service: $service\n";
2676237Sjacobs}
2686237Sjacobs
2696237Sjacobsif ($cmd eq 'print-service') {
2706237Sjacobs	my ($import_path, $export_path, $svc_name, $query, $migrate) = ();
2716237Sjacobs
2726237Sjacobs	my $res = GetOptions('q|query' => \$query, 's|set=s' => \$service,
2736237Sjacobs		'm|migrate' => \$migrate, 'e|export=s' => \$export_path,
2746237Sjacobs		'i|import=s' => \$import_path);
2756237Sjacobs
2766237Sjacobs	($res) || usage();
2776237Sjacobs
2786237Sjacobs	if (defined($import_path) && !defined($export_path) &&
2796237Sjacobs	    !defined($query) && !defined($service) && !defined($migrate)) {
2806237Sjacobs		import_print_queues($import_path);
2816237Sjacobs	} elsif (!defined($import_path) && defined($export_path) &&
2826237Sjacobs		 !defined($query) && !defined($service) && !defined($migrate)) {
2836237Sjacobs		export_print_queues($export_path);
2846237Sjacobs	} elsif (!defined($import_path) && !defined($export_path) &&
2856237Sjacobs		 defined($query) && !defined($service) && !defined($migrate)) {
2866237Sjacobs		query_service();
2876237Sjacobs	} elsif (!defined($import_path) && !defined($export_path) &&
2886237Sjacobs		 !defined($query) && defined($service)) {
2896237Sjacobs		select_service($service, $migrate);
2906237Sjacobs	} else {
2916237Sjacobs		usage();
2926237Sjacobs	}
2936237Sjacobs} else {
2946237Sjacobs	print_command($cmd, @ARGV);
2956237Sjacobs}
2966237Sjacobs
2976237Sjacobsexit(0);
298