xref: /illumos-gate/usr/src/cmd/print/selector/print-service (revision 36615d24946b849e48cedbbafa9adfb4a02b590c)
1#!/usr/perl5/bin/perl
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23# Use is subject to license terms.
24#
25# ident	"%Z%%M%	%I%	%E% SMI"
26#
27
28#
29# This program manages the "active" print service selection.
30#   If called as 'print-service', it takes one of four options.
31#   Options:
32#     [-s[et] service [-m]]	Select the "active" print service, optionally
33#				migrating basic print queue configuration.
34#     [-q[uery]]		Display the "active" print service.
35#     [-e[xport] file]		Export basic print queue configuration to
36#				a file.
37#     [-i[mport] file]		Import basic print queue configuration from
38#				a file.
39#
40#   If called by any other name, it will look for a corresponding command
41#   under /usr/lib/{active-service}/bin/{command} and execute that program
42#   with the original arguments.
43#
44
45use Getopt::Long;
46use File::Basename;
47use File::Copy;
48use File::Temp qw/ :POSIX /;
49
50my $cmd = basename($0);
51
52my $LPSTAT = '/usr/bin/lpstat';
53my $LPADMIN = '/usr/sbin/lpadmin';
54my $ENABLE = '/usr/bin/enable';
55my $ACCEPT = '/usr/sbin/accept';
56my $SVCADM = '/usr/sbin/svcadm';
57my $SVCPROP = '/usr/bin/svcprop';
58my $SVCCFG = '/usr/sbin/svccfg';
59my $SVC_LP_SCHEDULER = 'print/server';
60my $SVC_LP_LPD = 'print/rfc1179';
61my $SVC_LP_IPP = 'print/ipp-listener';
62my $SVC_LP_PPD = 'print/ppd-cache-update';
63my $SVC_CUPS_SCHEDULER = 'cups/scheduler';
64my $SVC_CUPS_LPD = 'cups/in-lpd';
65
66sub fatal {
67	print STDERR @_;
68	exit(1);
69}
70
71sub usage {
72	print STDERR <<EOF ;
73Usage:
74  $cmd [-s[et] service [-m]]	Select the \"active\" print service,
75					optionally migrating basic print queue
76					configuration.
77  $cmd [-q[uery]]		Display the "active" print service.
78  $cmd [-e[xport] file]	Export basic print queue configuration
79					to a file.
80  $cmd [-i[mport] file]	Import basic print queue configuration
81					from a file.
82EOF
83	exit(1);
84}
85
86sub svcprop {
87	local ($fmri, $property) = @_;
88	my $FH;
89
90	open($FH, "$SVCPROP -C -p $property $fmri 2>/dev/null |");
91	$result = <$FH>;
92	close($FH);
93
94	return ($result);
95}
96
97sub svccfg {
98	local ($fmri, $operation) = @_;
99	my $FH;
100
101	open($FH, "$SVCCFG -s $fmri \"$operation\" 2>/dev/null |");
102	$result = <$FH>;
103	close($FH);
104
105	return ($result);
106}
107
108sub svcadm {
109	local ($operation, @fmris) = @_;
110
111	system("$SVCADM $operation -s @fmris");
112}
113
114
115sub print_service {
116	my $service;
117
118	$service = svcprop("$SVC_CUPS_SCHEDULER:default", "general/active");
119	($service =~ /true/) && ($service = 'cups') || ($service = 'lp');
120
121	return ($service);
122}
123
124sub print_command {
125	local($command, @av) = @_;
126	my $service = print_service();
127
128	if (!defined($service)) {
129		fatal("failed to detect active print service: $!\n");
130	}
131
132	if (! -d "/usr/lib/$service/bin") {
133		fatal("print service: $service is not installed\n");
134	}
135
136	my $executable = "/usr/lib/$service/bin/$command";
137	# CUPS has it's own names for enable and disable
138	($command =~ /(en|dis)able/) && ($service eq 'cups') &&
139		(! -x $executable) &&
140		($executable = "/usr/lib/$service/bin/$service$command");
141
142	if (! -x $executable) {
143		fatal("$command is not available from $service print service\n");
144	}
145
146	exec($executable, @ARGV);
147}
148
149sub export_print_queues {
150	local ($path) = @_;
151	my $service = print_service();
152
153	if ($service eq 'lp') {
154		my $FH, $DFH;
155
156		open($FH, ">$path");
157		open($DFH, "$LPSTAT -v|");
158		while (<$DFH>) {
159			if (/device for (.+): (.+)/) {
160				my $EFH;
161
162				print $FH "<Printer $1>\nDeviceURI $2\n";
163				open($EFH, "$LPSTAT -p $1 -l |");
164				while (<$EFH>) {
165					(/Description: (.+)/) &&
166						print $FH "Info $1\n";
167				}
168				close($EFH);
169				print $FH "</Printer>\n";
170			}
171		}
172		close($DFH);
173		close($FH);
174	} else {
175		copy('/etc/cups/printers.conf', $path);
176	}
177}
178
179sub psystem {
180	print "  @_\n";
181	system(@_);
182}
183
184sub import_print_queues {
185	local ($path) = @_;
186	my $service = print_service();
187	my $FH, %printer, @options;
188
189	# store queue info in the 'active' print service
190	open($FH, "<$path");
191	while (<$FH>) {
192		if (/<Printer (.+)>/) {
193			$printer{'Printer'} = $1;
194			@options = ();
195			push(@options, "-p", $1);
196		} elsif (/([^\s]+)\s(.+)/) {
197			$printer{$1} = $2;
198			my $value = $2;
199			($1 eq 'DeviceURI') &&
200				push(@options, "-v", $value);
201			($1 eq 'Info') &&
202				push(@options, "-D", $value);
203		} elsif (/<\/Printer>/) {
204			($service eq 'lp') &&
205				push(@options, "-m", "uri");
206			print "importing $printer{'Printer'}...\n";
207			# create a queue
208			psystem($LPADMIN, @options);
209			psystem($ENABLE, $printer{'Printer'});
210			($printer{'Accepting'} eq 'Yes') &&
211				psystem($ACCEPT, $printer{'Printer'});
212			$printer = ();
213		}
214	}
215	close($FH);
216}
217
218sub select_service {
219	my ($service, $migrate) = @_;
220	my $FH, $queues;
221
222	if (! -d "/usr/lib/$service/bin") {
223		fatal("print service: $service is not installed\n");
224	}
225
226	if ($migrate == 1) {
227		# export old print queue configuration (if migrating)
228		$queues = tmpnam();
229		export_print_queues($queues);
230	}
231
232	# enable/disable the services
233	if ($service eq 'cups') {
234		(-f '/etc/printers.conf') && (! -f '/etc/lp/printers.conf') &&
235			rename('/etc/printers.conf', '/etc/lp/printers.conf');
236		print("disabling LP services...\n");
237		svcadm("disable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD,
238				  $SVC_LP_PPD);
239		print("enabling CUPS services...\n");
240		svcadm("enable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD);
241		svccfg("cups/scheduler:default",
242			"setprop general/active = boolean: true");
243	} else {
244		print("disabling CUPS services...\n");
245		svcadm("disable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD);
246		print("enabling LP services...\n");
247		svcadm("enable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD,
248				  $SVC_LP_PPD);
249		(-f '/etc/lp/printers.conf') &&
250			rename('/etc/lp/printers.conf', '/etc/printers.conf');
251		svccfg("cups/scheduler:default", "delprop general/active");
252	}
253
254	# import the new print queue configuration (if migrating)
255	defined($queues) && import_print_queues($queues);
256}
257
258sub query_service {
259	my $service = print_service();
260
261	if (!defined($service)) {
262		fatal("failed to detect active print service: $!\n");
263	}
264	print "active print service: $service\n";
265}
266
267if ($cmd eq 'print-service') {
268	my ($import_path, $export_path, $svc_name, $query, $migrate) = ();
269
270	my $res = GetOptions('q|query' => \$query, 's|set=s' => \$service,
271		'm|migrate' => \$migrate, 'e|export=s' => \$export_path,
272		'i|import=s' => \$import_path);
273
274	($res) || usage();
275
276	if (defined($import_path) && !defined($export_path) &&
277	    !defined($query) && !defined($service) && !defined($migrate)) {
278		import_print_queues($import_path);
279	} elsif (!defined($import_path) && defined($export_path) &&
280		 !defined($query) && !defined($service) && !defined($migrate)) {
281		export_print_queues($export_path);
282	} elsif (!defined($import_path) && !defined($export_path) &&
283		 defined($query) && !defined($service) && !defined($migrate)) {
284		query_service();
285	} elsif (!defined($import_path) && !defined($export_path) &&
286		 !defined($query) && defined($service)) {
287		select_service($service, $migrate);
288	} else {
289		usage();
290	}
291} else {
292	print_command($cmd, @ARGV);
293}
294
295exit(0);
296