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