xref: /illumos-gate/usr/src/cmd/print/selector/print-service (revision c1ecd8b9404ee0d96d93f02e82c441b9bb149a3d)
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';
6236615d24Sjacobsmy $SVC_LP_PPD = 'print/ppd-cache-update';
639622934aSjacobsmy $SVC_CUPS_SCHEDULER = 'cups/scheduler';
649622934aSjacobsmy $SVC_CUPS_LPD = 'cups/in-lpd';
659622934aSjacobs
669622934aSjacobssub fatal {
67*c1ecd8b9Sjacobs	($ENV{"DESKTOP_LAUNCHED"}) &&
68*c1ecd8b9Sjacobs		exec("/bin/zenity", "--error", "--text=@_");
699622934aSjacobs	print STDERR @_;
709622934aSjacobs	exit(1);
719622934aSjacobs}
729622934aSjacobs
739622934aSjacobssub usage {
749622934aSjacobs	print STDERR <<EOF ;
759622934aSjacobsUsage:
769622934aSjacobs  $cmd [-s[et] service [-m]]	Select the \"active\" print service,
779622934aSjacobs					optionally migrating basic print queue
789622934aSjacobs					configuration.
799622934aSjacobs  $cmd [-q[uery]]		Display the "active" print service.
809622934aSjacobs  $cmd [-e[xport] file]	Export basic print queue configuration
819622934aSjacobs					to a file.
829622934aSjacobs  $cmd [-i[mport] file]	Import basic print queue configuration
839622934aSjacobs					from a file.
849622934aSjacobsEOF
859622934aSjacobs	exit(1);
869622934aSjacobs}
879622934aSjacobs
889622934aSjacobssub svcprop {
899622934aSjacobs	local ($fmri, $property) = @_;
909622934aSjacobs	my $FH;
919622934aSjacobs
929622934aSjacobs	open($FH, "$SVCPROP -C -p $property $fmri 2>/dev/null |");
939622934aSjacobs	$result = <$FH>;
949622934aSjacobs	close($FH);
959622934aSjacobs
969622934aSjacobs	return ($result);
979622934aSjacobs}
989622934aSjacobs
999622934aSjacobssub svccfg {
1009622934aSjacobs	local ($fmri, $operation) = @_;
1019622934aSjacobs	my $FH;
1029622934aSjacobs
1039622934aSjacobs	open($FH, "$SVCCFG -s $fmri \"$operation\" 2>/dev/null |");
1049622934aSjacobs	$result = <$FH>;
1059622934aSjacobs	close($FH);
1069622934aSjacobs
1079622934aSjacobs	return ($result);
1089622934aSjacobs}
1099622934aSjacobs
1109622934aSjacobssub svcadm {
1119622934aSjacobs	local ($operation, @fmris) = @_;
1129622934aSjacobs
1139622934aSjacobs	system("$SVCADM $operation -s @fmris");
1149622934aSjacobs}
1159622934aSjacobs
1169622934aSjacobs
1179622934aSjacobssub print_service {
1189622934aSjacobs	my $service;
1199622934aSjacobs
1209622934aSjacobs	$service = svcprop("$SVC_CUPS_SCHEDULER:default", "general/active");
1219622934aSjacobs	($service =~ /true/) && ($service = 'cups') || ($service = 'lp');
1229622934aSjacobs
1239622934aSjacobs	return ($service);
1249622934aSjacobs}
1259622934aSjacobs
1269622934aSjacobssub print_command {
1279622934aSjacobs	local($command, @av) = @_;
1289622934aSjacobs	my $service = print_service();
1299622934aSjacobs
1309622934aSjacobs	if (!defined($service)) {
1319622934aSjacobs		fatal("failed to detect active print service: $!\n");
1329622934aSjacobs	}
1339622934aSjacobs
1349622934aSjacobs	if (! -d "/usr/lib/$service/bin") {
1359622934aSjacobs		fatal("print service: $service is not installed\n");
1369622934aSjacobs	}
1379622934aSjacobs
1389622934aSjacobs	my $executable = "/usr/lib/$service/bin/$command";
1399622934aSjacobs	# CUPS has it's own names for enable and disable
1409622934aSjacobs	($command =~ /(en|dis)able/) && ($service eq 'cups') &&
1419622934aSjacobs		(! -x $executable) &&
1429622934aSjacobs		($executable = "/usr/lib/$service/bin/$service$command");
1439622934aSjacobs
1449622934aSjacobs	if (! -x $executable) {
1459622934aSjacobs		fatal("$command is not available from $service print service\n");
1469622934aSjacobs	}
1479622934aSjacobs
1489622934aSjacobs	exec($executable, @ARGV);
1499622934aSjacobs}
1509622934aSjacobs
1519622934aSjacobssub export_print_queues {
1529622934aSjacobs	local ($path) = @_;
1539622934aSjacobs	my $service = print_service();
1549622934aSjacobs
1559622934aSjacobs	if ($service eq 'lp') {
1569622934aSjacobs		my $FH, $DFH;
1579622934aSjacobs
1589622934aSjacobs		open($FH, ">$path");
1599622934aSjacobs		open($DFH, "$LPSTAT -v|");
1609622934aSjacobs		while (<$DFH>) {
1619622934aSjacobs			if (/device for (.+): (.+)/) {
1629622934aSjacobs				my $EFH;
1639622934aSjacobs
1649622934aSjacobs				print $FH "<Printer $1>\nDeviceURI $2\n";
1659622934aSjacobs				open($EFH, "$LPSTAT -p $1 -l |");
1669622934aSjacobs				while (<$EFH>) {
1679622934aSjacobs					(/Description: (.+)/) &&
1689622934aSjacobs						print $FH "Info $1\n";
1699622934aSjacobs				}
1709622934aSjacobs				close($EFH);
1719622934aSjacobs				print $FH "</Printer>\n";
1729622934aSjacobs			}
1739622934aSjacobs		}
1749622934aSjacobs		close($DFH);
1759622934aSjacobs		close($FH);
1769622934aSjacobs	} else {
1779622934aSjacobs		copy('/etc/cups/printers.conf', $path);
1789622934aSjacobs	}
1799622934aSjacobs}
1809622934aSjacobs
1819622934aSjacobssub psystem {
1829622934aSjacobs	print "  @_\n";
1839622934aSjacobs	system(@_);
1849622934aSjacobs}
1859622934aSjacobs
1869622934aSjacobssub import_print_queues {
1879622934aSjacobs	local ($path) = @_;
1889622934aSjacobs	my $service = print_service();
1899622934aSjacobs	my $FH, %printer, @options;
1909622934aSjacobs
1919622934aSjacobs	# store queue info in the 'active' print service
1929622934aSjacobs	open($FH, "<$path");
1939622934aSjacobs	while (<$FH>) {
1949622934aSjacobs		if (/<Printer (.+)>/) {
1959622934aSjacobs			$printer{'Printer'} = $1;
1969622934aSjacobs			@options = ();
1979622934aSjacobs			push(@options, "-p", $1);
1989622934aSjacobs		} elsif (/([^\s]+)\s(.+)/) {
1999622934aSjacobs			$printer{$1} = $2;
2009622934aSjacobs			my $value = $2;
2019622934aSjacobs			($1 eq 'DeviceURI') &&
2029622934aSjacobs				push(@options, "-v", $value);
2039622934aSjacobs			($1 eq 'Info') &&
2049622934aSjacobs				push(@options, "-D", $value);
2059622934aSjacobs		} elsif (/<\/Printer>/) {
2069622934aSjacobs			($service eq 'lp') &&
2079622934aSjacobs				push(@options, "-m", "uri");
2089622934aSjacobs			print "importing $printer{'Printer'}...\n";
2099622934aSjacobs			# create a queue
2109622934aSjacobs			psystem($LPADMIN, @options);
2119622934aSjacobs			psystem($ENABLE, $printer{'Printer'});
2129622934aSjacobs			($printer{'Accepting'} eq 'Yes') &&
2139622934aSjacobs				psystem($ACCEPT, $printer{'Printer'});
2149622934aSjacobs			$printer = ();
2159622934aSjacobs		}
2169622934aSjacobs	}
2179622934aSjacobs	close($FH);
2189622934aSjacobs}
2199622934aSjacobs
2209622934aSjacobssub select_service {
2219622934aSjacobs	my ($service, $migrate) = @_;
2229622934aSjacobs	my $FH, $queues;
2239622934aSjacobs
2249622934aSjacobs	if (! -d "/usr/lib/$service/bin") {
2259622934aSjacobs		fatal("print service: $service is not installed\n");
2269622934aSjacobs	}
2279622934aSjacobs
2289622934aSjacobs	if ($migrate == 1) {
2299622934aSjacobs		# export old print queue configuration (if migrating)
2309622934aSjacobs		$queues = tmpnam();
2319622934aSjacobs		export_print_queues($queues);
2329622934aSjacobs	}
2339622934aSjacobs
2349622934aSjacobs	# enable/disable the services
2359622934aSjacobs	if ($service eq 'cups') {
23636615d24Sjacobs		(-f '/etc/printers.conf') && (! -f '/etc/lp/printers.conf') &&
23736615d24Sjacobs			rename('/etc/printers.conf', '/etc/lp/printers.conf');
2389622934aSjacobs		print("disabling LP services...\n");
23936615d24Sjacobs		svcadm("disable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD,
24036615d24Sjacobs				  $SVC_LP_PPD);
2419622934aSjacobs		print("enabling CUPS services...\n");
2429622934aSjacobs		svcadm("enable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD);
2439622934aSjacobs		svccfg("cups/scheduler:default",
2449622934aSjacobs			"setprop general/active = boolean: true");
2459622934aSjacobs	} else {
2469622934aSjacobs		print("disabling CUPS services...\n");
2479622934aSjacobs		svcadm("disable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD);
2489622934aSjacobs		print("enabling LP services...\n");
24936615d24Sjacobs		svcadm("enable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD,
25036615d24Sjacobs				  $SVC_LP_PPD);
25136615d24Sjacobs		(-f '/etc/lp/printers.conf') &&
25236615d24Sjacobs			rename('/etc/lp/printers.conf', '/etc/printers.conf');
2539622934aSjacobs		svccfg("cups/scheduler:default", "delprop general/active");
2549622934aSjacobs	}
2559622934aSjacobs
2569622934aSjacobs	# import the new print queue configuration (if migrating)
2579622934aSjacobs	defined($queues) && import_print_queues($queues);
2589622934aSjacobs}
2599622934aSjacobs
2609622934aSjacobssub query_service {
2619622934aSjacobs	my $service = print_service();
2629622934aSjacobs
2639622934aSjacobs	if (!defined($service)) {
2649622934aSjacobs		fatal("failed to detect active print service: $!\n");
2659622934aSjacobs	}
2669622934aSjacobs	print "active print service: $service\n";
2679622934aSjacobs}
2689622934aSjacobs
2699622934aSjacobsif ($cmd eq 'print-service') {
2709622934aSjacobs	my ($import_path, $export_path, $svc_name, $query, $migrate) = ();
2719622934aSjacobs
2729622934aSjacobs	my $res = GetOptions('q|query' => \$query, 's|set=s' => \$service,
2739622934aSjacobs		'm|migrate' => \$migrate, 'e|export=s' => \$export_path,
2749622934aSjacobs		'i|import=s' => \$import_path);
2759622934aSjacobs
2769622934aSjacobs	($res) || usage();
2779622934aSjacobs
2789622934aSjacobs	if (defined($import_path) && !defined($export_path) &&
2799622934aSjacobs	    !defined($query) && !defined($service) && !defined($migrate)) {
2809622934aSjacobs		import_print_queues($import_path);
2819622934aSjacobs	} elsif (!defined($import_path) && defined($export_path) &&
2829622934aSjacobs		 !defined($query) && !defined($service) && !defined($migrate)) {
2839622934aSjacobs		export_print_queues($export_path);
2849622934aSjacobs	} elsif (!defined($import_path) && !defined($export_path) &&
2859622934aSjacobs		 defined($query) && !defined($service) && !defined($migrate)) {
2869622934aSjacobs		query_service();
2879622934aSjacobs	} elsif (!defined($import_path) && !defined($export_path) &&
2889622934aSjacobs		 !defined($query) && defined($service)) {
2899622934aSjacobs		select_service($service, $migrate);
2909622934aSjacobs	} else {
2919622934aSjacobs		usage();
2929622934aSjacobs	}
2939622934aSjacobs} else {
2949622934aSjacobs	print_command($cmd, @ARGV);
2959622934aSjacobs}
2969622934aSjacobs
2979622934aSjacobsexit(0);
298