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