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_CUPS_SCHEDULER = 'cups/scheduler'; 63my $SVC_CUPS_LPD = 'cups/in-lpd'; 64 65sub fatal { 66 print STDERR @_; 67 exit(1); 68} 69 70sub usage { 71 print STDERR <<EOF ; 72Usage: 73 $cmd [-s[et] service [-m]] Select the \"active\" print service, 74 optionally migrating basic print queue 75 configuration. 76 $cmd [-q[uery]] Display the "active" print service. 77 $cmd [-e[xport] file] Export basic print queue configuration 78 to a file. 79 $cmd [-i[mport] file] Import basic print queue configuration 80 from a file. 81EOF 82 exit(1); 83} 84 85sub svcprop { 86 local ($fmri, $property) = @_; 87 my $FH; 88 89 open($FH, "$SVCPROP -C -p $property $fmri 2>/dev/null |"); 90 $result = <$FH>; 91 close($FH); 92 93 return ($result); 94} 95 96sub svccfg { 97 local ($fmri, $operation) = @_; 98 my $FH; 99 100 open($FH, "$SVCCFG -s $fmri \"$operation\" 2>/dev/null |"); 101 $result = <$FH>; 102 close($FH); 103 104 return ($result); 105} 106 107sub svcadm { 108 local ($operation, @fmris) = @_; 109 110 system("$SVCADM $operation -s @fmris"); 111} 112 113 114sub print_service { 115 my $service; 116 117 $service = svcprop("$SVC_CUPS_SCHEDULER:default", "general/active"); 118 ($service =~ /true/) && ($service = 'cups') || ($service = 'lp'); 119 120 return ($service); 121} 122 123sub print_command { 124 local($command, @av) = @_; 125 my $service = print_service(); 126 127 if (!defined($service)) { 128 fatal("failed to detect active print service: $!\n"); 129 } 130 131 if (! -d "/usr/lib/$service/bin") { 132 fatal("print service: $service is not installed\n"); 133 } 134 135 my $executable = "/usr/lib/$service/bin/$command"; 136 # CUPS has it's own names for enable and disable 137 ($command =~ /(en|dis)able/) && ($service eq 'cups') && 138 (! -x $executable) && 139 ($executable = "/usr/lib/$service/bin/$service$command"); 140 141 if (! -x $executable) { 142 fatal("$command is not available from $service print service\n"); 143 } 144 145 exec($executable, @ARGV); 146} 147 148sub export_print_queues { 149 local ($path) = @_; 150 my $service = print_service(); 151 152 if ($service eq 'lp') { 153 my $FH, $DFH; 154 155 open($FH, ">$path"); 156 open($DFH, "$LPSTAT -v|"); 157 while (<$DFH>) { 158 if (/device for (.+): (.+)/) { 159 my $EFH; 160 161 print $FH "<Printer $1>\nDeviceURI $2\n"; 162 open($EFH, "$LPSTAT -p $1 -l |"); 163 while (<$EFH>) { 164 (/Description: (.+)/) && 165 print $FH "Info $1\n"; 166 } 167 close($EFH); 168 print $FH "</Printer>\n"; 169 } 170 } 171 close($DFH); 172 close($FH); 173 } else { 174 copy('/etc/cups/printers.conf', $path); 175 } 176} 177 178sub psystem { 179 print " @_\n"; 180 system(@_); 181} 182 183sub import_print_queues { 184 local ($path) = @_; 185 my $service = print_service(); 186 my $FH, %printer, @options; 187 188 # store queue info in the 'active' print service 189 open($FH, "<$path"); 190 while (<$FH>) { 191 if (/<Printer (.+)>/) { 192 $printer{'Printer'} = $1; 193 @options = (); 194 push(@options, "-p", $1); 195 } elsif (/([^\s]+)\s(.+)/) { 196 $printer{$1} = $2; 197 my $value = $2; 198 ($1 eq 'DeviceURI') && 199 push(@options, "-v", $value); 200 ($1 eq 'Info') && 201 push(@options, "-D", $value); 202 } elsif (/<\/Printer>/) { 203 ($service eq 'lp') && 204 push(@options, "-m", "uri"); 205 print "importing $printer{'Printer'}...\n"; 206 # create a queue 207 psystem($LPADMIN, @options); 208 psystem($ENABLE, $printer{'Printer'}); 209 ($printer{'Accepting'} eq 'Yes') && 210 psystem($ACCEPT, $printer{'Printer'}); 211 $printer = (); 212 } 213 } 214 close($FH); 215} 216 217sub select_service { 218 my ($service, $migrate) = @_; 219 my $FH, $queues; 220 221 if (! -d "/usr/lib/$service/bin") { 222 fatal("print service: $service is not installed\n"); 223 } 224 225 if ($migrate == 1) { 226 # export old print queue configuration (if migrating) 227 $queues = tmpnam(); 228 export_print_queues($queues); 229 } 230 231 # enable/disable the services 232 if ($service eq 'cups') { 233 print("disabling LP services...\n"); 234 svcadm("disable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD); 235 print("enabling CUPS services...\n"); 236 svcadm("enable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD); 237 svccfg("cups/scheduler:default", 238 "setprop general/active = boolean: true"); 239 } else { 240 print("disabling CUPS services...\n"); 241 svcadm("disable", $SVC_CUPS_SCHEDULER, $SVC_CUPS_LPD); 242 print("enabling LP services...\n"); 243 svcadm("enable", $SVC_LP_SCHEDULER, $SVC_LP_IPP, $SVC_LP_LPD); 244 svccfg("cups/scheduler:default", "delprop general/active"); 245 } 246 247 # import the new print queue configuration (if migrating) 248 defined($queues) && import_print_queues($queues); 249} 250 251sub query_service { 252 my $service = print_service(); 253 254 if (!defined($service)) { 255 fatal("failed to detect active print service: $!\n"); 256 } 257 print "active print service: $service\n"; 258} 259 260if ($cmd eq 'print-service') { 261 my ($import_path, $export_path, $svc_name, $query, $migrate) = (); 262 263 my $res = GetOptions('q|query' => \$query, 's|set=s' => \$service, 264 'm|migrate' => \$migrate, 'e|export=s' => \$export_path, 265 'i|import=s' => \$import_path); 266 267 ($res) || usage(); 268 269 if (defined($import_path) && !defined($export_path) && 270 !defined($query) && !defined($service) && !defined($migrate)) { 271 import_print_queues($import_path); 272 } elsif (!defined($import_path) && defined($export_path) && 273 !defined($query) && !defined($service) && !defined($migrate)) { 274 export_print_queues($export_path); 275 } elsif (!defined($import_path) && !defined($export_path) && 276 defined($query) && !defined($service) && !defined($migrate)) { 277 query_service(); 278 } elsif (!defined($import_path) && !defined($export_path) && 279 !defined($query) && defined($service)) { 280 select_service($service, $migrate); 281 } else { 282 usage(); 283 } 284} else { 285 print_command($cmd, @ARGV); 286} 287 288exit(0); 289