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