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