xref: /illumos-gate/usr/src/cmd/print/selector/print-service (revision 36615d24946b849e48cedbbafa9adfb4a02b590c)
19622934aSjacobs#!/usr/perl5/bin/perl
29622934aSjacobs#
39622934aSjacobs# CDDL HEADER START
49622934aSjacobs#
59622934aSjacobs# The contents of this file are subject to the terms of the
69622934aSjacobs# Common Development and Distribution License (the "License").
79622934aSjacobs# You may not use this file except in compliance with the License.
89622934aSjacobs#
99622934aSjacobs# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
109622934aSjacobs# or http://www.opensolaris.org/os/licensing.
119622934aSjacobs# See the License for the specific language governing permissions
129622934aSjacobs# and limitations under the License.
139622934aSjacobs#
149622934aSjacobs# When distributing Covered Code, include this CDDL HEADER in each
159622934aSjacobs# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
169622934aSjacobs# If applicable, add the following below this CDDL HEADER, with the
179622934aSjacobs# fields enclosed by brackets "[]" replaced with your own identifying
189622934aSjacobs# information: Portions Copyright [yyyy] [name of copyright owner]
199622934aSjacobs#
209622934aSjacobs# CDDL HEADER END
219622934aSjacobs#
229622934aSjacobs# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
239622934aSjacobs# Use is subject to license terms.
249622934aSjacobs#
259622934aSjacobs# ident	"%Z%%M%	%I%	%E% SMI"
269622934aSjacobs#
279622934aSjacobs
289622934aSjacobs#
299622934aSjacobs# This program manages the "active" print service selection.
309622934aSjacobs#   If called as 'print-service', it takes one of four options.
319622934aSjacobs#   Options:
329622934aSjacobs#     [-s[et] service [-m]]	Select the "active" print service, optionally
339622934aSjacobs#				migrating basic print queue configuration.
349622934aSjacobs#     [-q[uery]]		Display the "active" print service.
359622934aSjacobs#     [-e[xport] file]		Export basic print queue configuration to
369622934aSjacobs#				a file.
379622934aSjacobs#     [-i[mport] file]		Import basic print queue configuration from
389622934aSjacobs#				a file.
399622934aSjacobs#
409622934aSjacobs#   If called by any other name, it will look for a corresponding command
419622934aSjacobs#   under /usr/lib/{active-service}/bin/{command} and execute that program
429622934aSjacobs#   with the original arguments.
439622934aSjacobs#
449622934aSjacobs
459622934aSjacobsuse Getopt::Long;
469622934aSjacobsuse File::Basename;
479622934aSjacobsuse File::Copy;
489622934aSjacobsuse File::Temp qw/ :POSIX /;
499622934aSjacobs
509622934aSjacobsmy $cmd = basename($0);
519622934aSjacobs
529622934aSjacobsmy $LPSTAT = '/usr/bin/lpstat';
539622934aSjacobsmy $LPADMIN = '/usr/sbin/lpadmin';
549622934aSjacobsmy $ENABLE = '/usr/bin/enable';
559622934aSjacobsmy $ACCEPT = '/usr/sbin/accept';
569622934aSjacobsmy $SVCADM = '/usr/sbin/svcadm';
579622934aSjacobsmy $SVCPROP = '/usr/bin/svcprop';
589622934aSjacobsmy $SVCCFG = '/usr/sbin/svccfg';
599622934aSjacobsmy $SVC_LP_SCHEDULER = 'print/server';
609622934aSjacobsmy $SVC_LP_LPD = 'print/rfc1179';
619622934aSjacobsmy $SVC_LP_IPP = 'print/ipp-listener';
62*36615d24Sjacobsmy $SVC_LP_PPD = 'print/ppd-cache-update';
639622934aSjacobsmy $SVC_CUPS_SCHEDULER = 'cups/scheduler';
649622934aSjacobsmy $SVC_CUPS_LPD = 'cups/in-lpd';
659622934aSjacobs
669622934aSjacobssub fatal {
679622934aSjacobs	print STDERR @_;
689622934aSjacobs	exit(1);
699622934aSjacobs}
709622934aSjacobs
719622934aSjacobssub usage {
729622934aSjacobs	print STDERR <<EOF ;
739622934aSjacobsUsage:
749622934aSjacobs  $cmd [-s[et] service [-m]]	Select the \"active\" print service,
759622934aSjacobs					optionally migrating basic print queue
769622934aSjacobs					configuration.
779622934aSjacobs  $cmd [-q[uery]]		Display the "active" print service.
789622934aSjacobs  $cmd [-e[xport] file]	Export basic print queue configuration
799622934aSjacobs					to a file.
809622934aSjacobs  $cmd [-i[mport] file]	Import basic print queue configuration
819622934aSjacobs					from a file.
829622934aSjacobsEOF
839622934aSjacobs	exit(1);
849622934aSjacobs}
859622934aSjacobs
869622934aSjacobssub svcprop {
879622934aSjacobs	local ($fmri, $property) = @_;
889622934aSjacobs	my $FH;
899622934aSjacobs
909622934aSjacobs	open($FH, "$SVCPROP -C -p $property $fmri 2>/dev/null |");
919622934aSjacobs	$result = <$FH>;
929622934aSjacobs	close($FH);
939622934aSjacobs
949622934aSjacobs	return ($result);
959622934aSjacobs}
969622934aSjacobs
979622934aSjacobssub svccfg {
989622934aSjacobs	local ($fmri, $operation) = @_;
999622934aSjacobs	my $FH;
1009622934aSjacobs
1019622934aSjacobs	open($FH, "$SVCCFG -s $fmri \"$operation\" 2>/dev/null |");
1029622934aSjacobs	$result = <$FH>;
1039622934aSjacobs	close($FH);
1049622934aSjacobs
1059622934aSjacobs	return ($result);
1069622934aSjacobs}
1079622934aSjacobs
1089622934aSjacobssub svcadm {
1099622934aSjacobs	local ($operation, @fmris) = @_;
1109622934aSjacobs
1119622934aSjacobs	system("$SVCADM $operation -s @fmris");
1129622934aSjacobs}
1139622934aSjacobs
1149622934aSjacobs
1159622934aSjacobssub print_service {
1169622934aSjacobs	my $service;
1179622934aSjacobs
1189622934aSjacobs	$service = svcprop("$SVC_CUPS_SCHEDULER:default", "general/active");
1199622934aSjacobs	($service =~ /true/) && ($service = 'cups') || ($service = 'lp');
1209622934aSjacobs
1219622934aSjacobs	return ($service);
1229622934aSjacobs}
1239622934aSjacobs
1249622934aSjacobssub print_command {
1259622934aSjacobs	local($command, @av) = @_;
1269622934aSjacobs	my $service = print_service();
1279622934aSjacobs
1289622934aSjacobs	if (!defined($service)) {
1299622934aSjacobs		fatal("failed to detect active print service: $!\n");
1309622934aSjacobs	}
1319622934aSjacobs
1329622934aSjacobs	if (! -d "/usr/lib/$service/bin") {
1339622934aSjacobs		fatal("print service: $service is not installed\n");
1349622934aSjacobs	}
1359622934aSjacobs
1369622934aSjacobs	my $executable = "/usr/lib/$service/bin/$command";
1379622934aSjacobs	# CUPS has it's own names for enable and disable
1389622934aSjacobs	($command =~ /(en|dis)able/) && ($service eq 'cups') &&
1399622934aSjacobs		(! -x $executable) &&
1409622934aSjacobs		($executable = "/usr/lib/$service/bin/$service$command");
1419622934aSjacobs
1429622934aSjacobs	if (! -x $executable) {
1439622934aSjacobs		fatal("$command is not available from $service print service\n");
1449622934aSjacobs	}
1459622934aSjacobs
1469622934aSjacobs	exec($executable, @ARGV);
1479622934aSjacobs}
1489622934aSjacobs
1499622934aSjacobssub export_print_queues {
1509622934aSjacobs	local ($path) = @_;
1519622934aSjacobs	my $service = print_service();
1529622934aSjacobs
1539622934aSjacobs	if ($service eq 'lp') {
1549622934aSjacobs		my $FH, $DFH;
1559622934aSjacobs
1569622934aSjacobs		open($FH, ">$path");
1579622934aSjacobs		open($DFH, "$LPSTAT -v|");
1589622934aSjacobs		while (<$DFH>) {
1599622934aSjacobs			if (/device for (.+): (.+)/) {
1609622934aSjacobs				my $EFH;
1619622934aSjacobs
1629622934aSjacobs				print $FH "<Printer $1>\nDeviceURI $2\n";
1639622934aSjacobs				open($EFH, "$LPSTAT -p $1 -l |");
1649622934aSjacobs				while (<$EFH>) {
1659622934aSjacobs					(/Description: (.+)/) &&
1669622934aSjacobs						print $FH "Info $1\n";
1679622934aSjacobs				}
1689622934aSjacobs				close($EFH);
1699622934aSjacobs				print $FH "</Printer>\n";
1709622934aSjacobs			}
1719622934aSjacobs		}
1729622934aSjacobs		close($DFH);
1739622934aSjacobs		close($FH);
1749622934aSjacobs	} else {
1759622934aSjacobs		copy('/etc/cups/printers.conf', $path);
1769622934aSjacobs	}
1779622934aSjacobs}
1789622934aSjacobs
1799622934aSjacobssub psystem {
1809622934aSjacobs	print "  @_\n";
1819622934aSjacobs	system(@_);
1829622934aSjacobs}
1839622934aSjacobs
1849622934aSjacobssub import_print_queues {
1859622934aSjacobs	local ($path) = @_;
1869622934aSjacobs	my $service = print_service();
1879622934aSjacobs	my $FH, %printer, @options;
1889622934aSjacobs
1899622934aSjacobs	# store queue info in the 'active' print service
1909622934aSjacobs	open($FH, "<$path");
1919622934aSjacobs	while (<$FH>) {
1929622934aSjacobs		if (/<Printer (.+)>/) {
1939622934aSjacobs			$printer{'Printer'} = $1;
1949622934aSjacobs			@options = ();
1959622934aSjacobs			push(@options, "-p", $1);
1969622934aSjacobs		} elsif (/([^\s]+)\s(.+)/) {
1979622934aSjacobs			$printer{$1} = $2;
1989622934aSjacobs			my $value = $2;
1999622934aSjacobs			($1 eq 'DeviceURI') &&
2009622934aSjacobs				push(@options, "-v", $value);
2019622934aSjacobs			($1 eq 'Info') &&
2029622934aSjacobs				push(@options, "-D", $value);
2039622934aSjacobs		} elsif (/<\/Printer>/) {
2049622934aSjacobs			($service eq 'lp') &&
2059622934aSjacobs				push(@options, "-m", "uri");
2069622934aSjacobs			print "importing $printer{'Printer'}...\n";
2079622934aSjacobs			# create a queue
2089622934aSjacobs			psystem($LPADMIN, @options);
2099622934aSjacobs			psystem($ENABLE, $printer{'Printer'});
2109622934aSjacobs			($printer{'Accepting'} eq 'Yes') &&
2119622934aSjacobs				psystem($ACCEPT, $printer{'Printer'});
2129622934aSjacobs			$printer = ();
2139622934aSjacobs		}
2149622934aSjacobs	}
2159622934aSjacobs	close($FH);
2169622934aSjacobs}
2179622934aSjacobs
2189622934aSjacobssub select_service {
2199622934aSjacobs	my ($service, $migrate) = @_;
2209622934aSjacobs	my $FH, $queues;
2219622934aSjacobs
2229622934aSjacobs	if (! -d "/usr/lib/$service/bin") {
2239622934aSjacobs		fatal("print service: $service is not installed\n");
2249622934aSjacobs	}
2259622934aSjacobs
2269622934aSjacobs	if ($migrate == 1) {
2279622934aSjacobs		# export old print queue configuration (if migrating)
2289622934aSjacobs		$queues = tmpnam();
2299622934aSjacobs		export_print_queues($queues);
2309622934aSjacobs	}
2319622934aSjacobs
2329622934aSjacobs	# enable/disable the services
2339622934aSjacobs	if ($service eq 'cups') {
234*36615d24Sjacobs		(-f '/etc/printers.conf') && (! -f '/etc/lp/printers.conf') &&
235*36615d24Sjacobs			rename('/etc/printers.conf', '/etc/lp/printers.conf');
2369622934aSjacobs		print("disabling LP services...\n");
237*36615d24Sjacobs		svcadm("disable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD,
238*36615d24Sjacobs				  $SVC_LP_PPD);
2399622934aSjacobs		print("enabling CUPS services...\n");
2409622934aSjacobs		svcadm("enable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD);
2419622934aSjacobs		svccfg("cups/scheduler:default",
2429622934aSjacobs			"setprop general/active = boolean: true");
2439622934aSjacobs	} else {
2449622934aSjacobs		print("disabling CUPS services...\n");
2459622934aSjacobs		svcadm("disable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD);
2469622934aSjacobs		print("enabling LP services...\n");
247*36615d24Sjacobs		svcadm("enable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD,
248*36615d24Sjacobs				  $SVC_LP_PPD);
249*36615d24Sjacobs		(-f '/etc/lp/printers.conf') &&
250*36615d24Sjacobs			rename('/etc/lp/printers.conf', '/etc/printers.conf');
2519622934aSjacobs		svccfg("cups/scheduler:default", "delprop general/active");
2529622934aSjacobs	}
2539622934aSjacobs
2549622934aSjacobs	# import the new print queue configuration (if migrating)
2559622934aSjacobs	defined($queues) && import_print_queues($queues);
2569622934aSjacobs}
2579622934aSjacobs
2589622934aSjacobssub query_service {
2599622934aSjacobs	my $service = print_service();
2609622934aSjacobs
2619622934aSjacobs	if (!defined($service)) {
2629622934aSjacobs		fatal("failed to detect active print service: $!\n");
2639622934aSjacobs	}
2649622934aSjacobs	print "active print service: $service\n";
2659622934aSjacobs}
2669622934aSjacobs
2679622934aSjacobsif ($cmd eq 'print-service') {
2689622934aSjacobs	my ($import_path, $export_path, $svc_name, $query, $migrate) = ();
2699622934aSjacobs
2709622934aSjacobs	my $res = GetOptions('q|query' => \$query, 's|set=s' => \$service,
2719622934aSjacobs		'm|migrate' => \$migrate, 'e|export=s' => \$export_path,
2729622934aSjacobs		'i|import=s' => \$import_path);
2739622934aSjacobs
2749622934aSjacobs	($res) || usage();
2759622934aSjacobs
2769622934aSjacobs	if (defined($import_path) && !defined($export_path) &&
2779622934aSjacobs	    !defined($query) && !defined($service) && !defined($migrate)) {
2789622934aSjacobs		import_print_queues($import_path);
2799622934aSjacobs	} elsif (!defined($import_path) && defined($export_path) &&
2809622934aSjacobs		 !defined($query) && !defined($service) && !defined($migrate)) {
2819622934aSjacobs		export_print_queues($export_path);
2829622934aSjacobs	} elsif (!defined($import_path) && !defined($export_path) &&
2839622934aSjacobs		 defined($query) && !defined($service) && !defined($migrate)) {
2849622934aSjacobs		query_service();
2859622934aSjacobs	} elsif (!defined($import_path) && !defined($export_path) &&
2869622934aSjacobs		 !defined($query) && defined($service)) {
2879622934aSjacobs		select_service($service, $migrate);
2889622934aSjacobs	} else {
2899622934aSjacobs		usage();
2909622934aSjacobs	}
2919622934aSjacobs} else {
2929622934aSjacobs	print_command($cmd, @ARGV);
2939622934aSjacobs}
2949622934aSjacobs
2959622934aSjacobsexit(0);
296