package printer; use Data::Dumper; use common qw(:common :system); use commands; my $prefix = ""; my $PRINTER_DB_FILE = "/usr/lib/rhs/rhs-printfilters/printerdb"; my $PRINTER_FILTER_DIR = "/usr/lib/rhs/rhs-printfilters"; %printer_type = ( __("Local printer") => "LOCAL", __("Remote lpd") => "REMOTE", __("SMB/Windows 95/98/NT") => "SMB", __("NetWare") => "NCP", ); %printer_type_inv = reverse %printer_type; $printer_type_default = "Local printer"; %fields = ( STANDARD => [qw(QUEUE SPOOLDIR IF)], SPEC => [qw(DBENTRY RESOLUTION PAPERSIZE BITSPERPIXEL CRLF)], LOCAL => [qw(DEVICE)], REMOTE => [qw(REMOTEHOST REMOTEQUEUE)], SMB => [qw(SMBHOST SMBHOSTIP SMBSHARE SMBUSER SMBPASSWD SMBWORKGROUP AF)], NCP => [qw(NCPHOST NCPQUEUE NCPUSER NCPPASSWD)], ); @papersize_type = qw(letter legal ledger a3 a4); $spooldir = "/var/spool/lpd"; sub set_prefix($) { $prefix = $_[0]; } sub read_printer_db(;$) { my $dbpath = $prefix . ($_[0] || $PRINTER_DB_FILE); %thedb and return; my %available_devices; local *AVAIL; open AVAIL, "chroot ". ($prefix || '/') ." /usr/bin/gs --help |"; foreach () { if (/^Available devices:/ ... /^\S/) { @available_devices{split /\s+/, $_} = () if /^\s+/; } } delete $available_devices{''}; @available_devices{qw/POSTSCRIPT TEXT/} = (); close AVAIL; local $_; local *DBPATH; open DBPATH, $dbpath or die "An error has occurred on $dbpath : $!"; while () { if (/^StartEntry:\s(\w*)/) { my $entryname = $1; my $entry; $entry->{ENTRY} = $entryname; WHILE : while () { SWITCH: { /GSDriver:\s*(\w*)/ and do { $entry->{GSDRIVER} = $1; last SWITCH }; /Description:\s*{(.*)}/ and do { $entry->{DESCR} = $1; last SWITCH }; /About:\s*{(.*)}/ and do { $entry->{ABOUT} = $1; last SWITCH }; /About:\s*{(.*)/ and do { my $string = "$1\n"; while () { /(.*)}/ and do { $entry->{ABOUT} = $string; last SWITCH }; $string .= $_; } }; /Resolution:\s*{(.*)}\s*{(.*)}\s*{(.*)}/ and do { push @{$entry->{RESOLUTION}}, { XDPI => $1, YDPI => $2, DESCR => $3 }; last SWITCH }; /BitsPerPixel:\s*{(.*)}\s*{(.*)}/ and do { push @{$entry->{BITSPERPIXEL}}, {DEPTH => $1, DESCR => $2}; last SWITCH }; /EndEntry/ and last WHILE; } } if (exists $available_devices{$entry->{GSDRIVER}}) { $thedb{$entryname} = $entry; $thedb_gsdriver{$entry->{GSDRIVER}} = $entry; } } } @entries_db_short = sort keys %printer::thedb; @entry_db_description = map { $printer::thedb{$_}{DESCR} } @entries_db_short; %descr_to_db = map { $printer::thedb{$_}{DESCR}, $_ } @entries_db_short; %db_to_descr = reverse %descr_to_db; } sub create_spool_dir($) { my ($queue_path) = @_; my $complete_path = "$prefix/$queue_path"; unless (-d $complete_path) { mkdir "$complete_path", 0755 or die "An error has occurred - can't create $complete_path : $!"; } my $gid_lp = (getpwnam("lp"))[3]; chown 0, $gid_lp, $complete_path or die "An error has occurred - can't chgrp $complete_path to lp $!"; } sub create_config_file($$%) { my ($inputfile, $outputfile, %toreplace) = @_; template2file("$prefix/$inputfile", "$prefix/$outputfile", %toreplace); } sub copy_master_filter($) { my ($queue_path) = @_; my $complete_path = "$prefix/$queue_path/filter"; my $master_filter = "$prefix/$PRINTER_FILTER_DIR/master-filter"; eval { commands::cp('-f', $master_filter, $complete_path) }; $@ and die "Can't copy $master_filter to $complete_path $!"; } my $intro_printcap_test = " # # Please don't edit this file directly unless you know what you are doing! # Look at the printcap(5) man page for more info. # Be warned that the control-panel printtool requires a very strict format! # Look at the printcap(5) man page for more info. # # This file can be edited with the printtool in the control-panel. # "; sub read_configured_queue($) { my ($entry) = @_; my $current = undef; local *PRINTCAP; open PRINTCAP, "$prefix/etc/printcap" or die "Can't open printcap file $!"; foreach () { chomp; my $p = '(?:\{(.*?)\}|(\S+))'; if (/^##PRINTTOOL3##\s+$p\s+$p\s+$p\s+$p\s+$p\s+$p\s+$p(?:\s+$p)?/) { if ($current) { add2hash($entry->{configured}{$current->{QUEUE}} ||= {}, $current); $current = undef; } $current = { TYPE => $1 || $2, GSDRIVER => $3 || $4, RESOLUTION => $5 || $6, PAPERSIZE => $7 || $8, DBENTRY => $11 || $12, BITSPERPIXEL => $13 || $14, CRLF => $15 || $16, }; } elsif (/^([^:]*):\\/) { $current->{QUEUE} = $1; } elsif (/^\s+:sd=([^:]*):\\/) { $current->{SPOOLDIR} = $1; } elsif (/^\s+:lp=([^:]*):\\/) { $current->{DEVICE} = $1; } elsif (/^\s+:rm=([^:]*):\\/) { $current->{REMOTEHOST} = $1; } elsif (/^\s+:rp=([^:]*):\\/) { $current->{REMOTEQUEUE} = $1; } } if ($current) { add2hash($entry->{configured}{$current->{QUEUE}} ||= {}, $current); $current = undef; } foreach (values %{$entry->{configured}}) { if ($_->{TYPE} eq 'SMB') { my $config_file = "$prefix$_->{SPOOLDIR}/.config"; local *F; open F, "$config_file" or die "Can't open $config_file $!"; foreach () { chomp; if (/^\s*share='\\\\(.*?)\\(.*?)'/) { $_->{SMBHOST} = $1; $_->{SMBSHARE} = $2; } elsif (/^\s*hostip=(.*)/) { $_->{SMBHOSTIP} = $1; } elsif (/^\s*user='(.*)'/) { $_->{SMBUSER} = $1; } elsif (/^\s*password='(.*)'/) { $_->{SMBPASSWD} = $1; } elsif (/^\s*workgroup='(.*)'/) { $_->{SMBWORKGROUP} = $1; } } } elsif ($_->{TYPE} eq 'NCP') { my $config_file = "$prefix$_->{SPOOLDIR}/.config"; local *F; open F, "$config_file" or die "Can't open $config_file $!"; foreach () { chomp; if (/^\s*server=(.*)/) { $_->{NCPHOST} = $1; } elsif (/^\s*user='(.*)'/) { $_->{NCPUSER} = $1; } elsif (/^\s*password='(.*)'/) { $_->{NCPPASSWD} = $1; } elsif (/^\s*queue='(.*)'/) { $_->{NCPQUEUE} = $1; } } } } } sub configure_queue($) { my ($entry) = @_; $entry->{SPOOLDIR} ||= "$spooldir"; $entry->{IF} ||= "$spooldir/$entry->{QUEUE}/filter"; $entry->{AF} ||= "$spooldir/$entry->{QUEUE}/acct"; my $queue_path = "$entry->{SPOOLDIR}"; create_spool_dir($queue_path); my $get_name_file = sub { my ($name) = @_; ("$PRINTER_FILTER_DIR/$name.in", "$entry->{SPOOLDIR}/$name") }; my ($filein, $file); my %fieldname = (); my $dbentry = $thedb{($entry->{DBENTRY})} or die "no dbentry"; ($filein, $file) = &$get_name_file("general.cfg"); $fieldname{ascps_trans} = ($dbentry->{GSDRIVER} eq "POSTSCRIPT") ? "YES" : "NO"; $fieldname{desiredto} = ($dbentry->{GSDRIVER} ne "TEXT") ? "ps" : "asc"; $fieldname{papersize} = $entry->{PAPERSIZE} ? $entry->{PAPERSIZE} : "letter"; $fieldname{printertype} = $entry->{TYPE}; create_config_file($filein, $file, %fieldname); ($filein, $file) = &$get_name_file("postscript.cfg"); %fieldname = (); $fieldname{gsdevice} = $dbentry->{GSDRIVER}; $fieldname{papersize} = $entry->{PAPERSIZE} ? $entry->{PAPERSIZE} : "letter"; $fieldname{resolution} = $entry->{RESOLUTION}; $fieldname{color} = $entry->{BITSPERPIXEL} ne "Default" && (($dbentry->{GSDRIVER} ne "uniprint" && "-dBitsPerPixel=") . $entry->{BITSPERPIXEL}); $fieldname{reversepages} = "NO"; $fieldname{extragsoptions} = ""; $fieldname{pssendeof} = $entry->{AUTOSENDEOF} ? ($dbentry->{GSDRIVER} eq "POSTSCRIPT" ? "YES" : "NO") : "NO"; $fieldname{nup} = "1"; $fieldname{rtlftmar} = "18"; $fieldname{topbotmar} = "18"; create_config_file($filein, $file, %fieldname); ($filein, $file) = &$get_name_file("textonly.cfg"); %fieldname = (); $fieldname{textonlyoptions} = ""; $fieldname{crlftrans} = $entry->{CRLF} ? "YES" : ""; $fieldname{textsendeof} = $entry->{AUTOSENDEOF} ? ($dbentry->{GSDRIVER} eq "POSTSCRIPT" ? "NO" : "YES") : "NO"; create_config_file($filein, $file, %fieldname); if ($entry->{TYPE} eq "SMB") { my $config_file = "$prefix$queue_path/.config"; local *F; open F, ">$config_file" or die "Can't create $config_file $!"; print F "share='\\\\$entry->{SMBHOST}\\$entry->{SMBSHARE}'\n"; print F "hostip=$entry->{SMBHOSTIP}\n"; print F "user='$entry->{SMBUSER}'\n"; print F "password='$entry->{SMBPASSWD}'\n"; print F "workgroup='$entry->{SMBWORKGROUP}'\n"; } elsif ($entry->{TYPE} eq "NCP") { my $config_file = "$prefix$queue_path/.config"; local *F; open F, ">$config_file" or die "Can't create $config_file $!"; print F "server=$entry->{NCPHOST}\n"; print F "queue=$entry->{NCPQUEUE}\n"; print F "user=$entry->{NCPUSER}\n"; print F "password=$entry->{NCPPASSWD}\n"; } copy_master_filter($queue_path); local *PRINTCAP; if ($::testing) { *PRINTCAP = *STDOUT; } else { open PRINTCAP, ">$prefix/etc/printcap" or die "Can't open printcap file $!"; } print PRINTCAP $intro_printcap_test; foreach (values %{$entry->{configured}}) { my $db_ = $thedb{($_->{DBENTRY})} or die "no dbentry"; printf PRINTCAP "##PRINTTOOL3## %s %s %s %s %s %s %s%s\n", $_->{TYPE} || '{}', $db_->{GSDRIVER} || '{}', $_->{RESOLUTION} || '{}', $_->{PAPERSIZE} || '{}', '{}', $db_->{ENTRY} || '{}', $_->{BITSPERPIXEL} || '{}', $_->{CRLF} ? " 1" : ""; print PRINTCAP "$_->{QUEUE}:\\\n"; print PRINTCAP "\t:sd=$_->{SPOOLDIR}:\\\n"; print PRINTCAP "\t:mx#0:\\\n\t:sh:\\\n"; if ($_->{TYPE} eq "LOCAL") { print PRINTCAP "\t:lp=$_->{DEVICE}:\\\n"; } elsif ($_->{TYPE} eq "REMOTE") { print PRINTCAP "\t:rm=$_->{REMOTEHOST}:\\\n"; print PRINTCAP "\t:rp=$_->{REMOTEQUEUE}:\\\n"; } else { print PRINTCAP "\t:lp=/dev/null:\\\n"; print PRINTCAP "\t:af=$_->{SPOOLDIR}/acct\\\n"; } print PRINTCAP "\t:if=$_->{SPOOLDIR}/filter:\n"; print PRINTCAP "\n"; } } sub test { $::testing = 1; $printer::prefix=""; read_printer_db(); print "the dump\n"; print Dumper(%thedb); # #eval { printer::create_spool_dir("/tmp/titi/", ".") }; #print $@; #eval { printer::copy_master_filter("/tmp/titi/", ".") }; #print $@; # # #eval { printer::create_config_file("files/postscript.cfg.in", "files/postscript.cfg","./", # ( # gsdevice => "titi", # resolution => "tata", # )); # }; #print $@; # # # #printer::configure_queue(\%printer::ex_printcap_entry, "/"); } 1; #