#!/bin/sh # \ exec tclsh $0 ${1+"$@"} set Prog [lindex [split $argv0 /] end] # BEGIN CONFIGURATION ######################################################## # Your domain, if any: set Net .ucolick.org # END CONFIGURATION ########################################################## proc usage {} { global Prog argv puts "Use: $Prog \[-h] \[-f pcfile] \[printer...] `$Prog' reads /etc/printcap or /etc/printers.conf (whichever is more recent), and prints the description of each printer named on the command line. If no printers are listed, it lists the names of all known printers. The default printer is flagged with \"***\". (Note: each command-line arg is treated as glob pattern.) The special printer name 'local' or 'attached' means to print details of all attached printers, ie printers for which there is no \"rm\" field. Options: -------- -f pcfile Use pcfile instead of /etc/printcap or /etc/printers.conf. " } proc shift {} { global argv ; set argv [lrange $argv 1 end] } proc nextarg {} {global argv; set a [lindex $argv 0]; shift; return $a} set printcapfile "" while {[string match -* [set opt [lindex $argv 0]]]} { if [string match $opt* -help] { usage ; exit 0 } elseif [string match $opt* -file] { shift; set printcapfile [nextarg] } elseif {"$opt" == "--"} { shift; break } } # Just summarize if no args are given. set summarizing [expr [llength $argv] == 0] set show_attached 0 if {[lsearch $argv "local"] >= 0 || [lsearch $argv "attached"] >= 0} { set show_attached 1 } ### puts "summarizing $summarizing show_attached $show_attached" ### puts "[llength $argv] <$argv>" # Whitespace pattern: set WS "\[ \t\]*" set hostname [info hostname] regexp {^([^.]+)\.} $hostname junk hostpart regexp {^[^.]+(.*)} $hostname junk netpart if ![string compare $netpart ""] {set netpart $Net} if ![string match .* $netpart] { set netpart ".$netpart" } set myhostpat "${hostpart}($netpart)?" regsub -all {\.} $myhostpat {\.} myhostpat if {"$printcapfile" == ""} { set printcapfile /etc/printcap set mtime [file mtime $printcapfile] set f /etc/printers.conf if [file exists $f] { set t [file mtime $f] if {$t > $mtime} { set printcapfile $f } } } puts "\t\[ Using $printcapfile ]" if [catch {open $printcapfile r} hdl] { puts $hdl exit } # Read the printcap set printcap [read $hdl] close $hdl # Get rid of comments: regsub -all "\n$WS#\[^\n]*" $printcap "" printcap regsub "^$WS#\[^\n]*" $printcap "" printcap # Join the continued lines: # (Note that "\\\\\n" is converted by the tcl interpreter into # backslash-backslash-newline, and that regsub treats backslash # as a magic character, but backslash-backslash is plain backslash. # Hence the meaning of "\\\\\n" is is backslash-newline. regsub -all "\\\\\n$WS" $printcap "" printcap # Sort the printcap entries: set entries [lsort [split $printcap \n]] # # FieldInfo contains information about printcap fields. # Each value is a list, of format {type default meaning}. # array set FieldInfo { af { str NULL "Name of accounting file" } br { num none "set the baud rate for tty lp's." } cf { str NULL "The cifplot data filter." } ct { str dev "Connection type: dev, LAT, remote." } df { str NULL "Tex data filter (DVI format)." } fc { num 0 "If lp is a tty, clear flag bits in sgtty.h." } ff { str \f "String to send for a form feed." } fo { bool false "Print form feed when device is opened." } fs { num 0 "If lp is a tty, set flag bits in sgtty.h." } gf { str NULL "Graph data filter (plot format)." } hl { bool false "Print the burst header page last." } ic { bool false "Driver has special ioctl to indent printout." } if { str NULL "Name of text filter that does accounting." } lf { str /dev/console "Error-logging filename." } lo { str lock "Name of lock file." } lp { str /dev/lp "Device name to open for output." } mc { num 0 "maximum number of copies." } mx { num 1000 "Max file size, in BUFSIZ blks. 0=inf." } nf { str NULL "Ditroff data filter." } of { str NULL "Name of output filtering program." } pl { num 66 "Page length (in lines)." } pw { num 132 "Page width (in columns)." } px { num 0 "Page width in pixels (horizontal)." } py { num 0 "Page length in pixels (vertical)." } rf { str NULL "Filter for FORTRAN style text files." } rm { str NULL "Machine name for remote printer." } rp { str lp "Remote printer name argument." } rs { bool false "Remote users must have local accounts." } rw { bool false "Open printer device for reading and writing." } sb { bool false "Short banner (one line only)." } sc { bool false "Suppress multiple copies." } sd { str /usr/spool/lpd "Spool directory." } sf { bool false "Suppress form feeds." } sh { bool false "Suppress burst page header." } st { str status "Status filename." } tf { str NULL "Troff data filter." } tr { str NULL "Trailer string to print when queue empties." } vf { str NULL "Raster image filter." } xc { num 0 "If lp is a tty, clear tty local mode bits." } xf { str NULL "Pass-through filter." } xs { num 0 "If lp is a tty, set tty local mode bits." } ya { str NULL "Additional parameters for print filter (I18N)." } } # And print the names and descriptions: foreach entry $entries { if [regexp "^$WS\$" $entry] { # empty line continue } # Normalize the entry into list form. regsub -all "::+" $entry ":" entry set entry [split $entry ":"] # Extract the printer names from the entry set names [split [lindex $entry 0] "|"] set primary [lindex $names 0] set descr [lindex $names end] set othernames [lrange $names 1 [expr [llength $names] - 2]] # Get rid of duplicates catch {unset x} set x($primary) $primary set aliases {} foreach a $othernames { if ![info exists x($a)] { set x($a) $a lappend aliases $a } } set these_printers [concat [list $primary] $aliases] if {[lsearch $these_printers "lp"] >= 0} { set suffix "\t\t***" } else { set suffix "" } if !$summarizing { # Check if this printer is listed in the args # Printer is non-local if rm=xxx is present, or if bsdaddr=xxx # is present but xxx doesn't match our host. set match [expr $show_attached \ && [lsearch -regexp $entry "^rm=.*"] == -1 \ && ([lsearch -regexp $entry "^bsdaddr="] == -1 || \ [lsearch -regexp $entry "^bsdaddr=$myhostpat"] != -1)] if !$match { foreach p $argv { if {[lsearch -glob $these_printers $p] >= 0} { set match 1 break } } } if !$match { # Don't print anything about this printer continue } } if [llength $aliases] { puts "\n$primary ([join $aliases {, }]): $suffix\n\t$descr" } else { puts "\n$primary: $suffix\n\t$descr" } if !$summarizing { # Print the rest of the entry, 1 keyword per line. # # Annotate the entry set antry {} foreach field [lrange $entry 1 end] { if {[string compare $field ""] == 0} { continue } set key [lindex [split $field "=#"] 0] if [info exists FieldInfo($key)] { set meaning [lindex $FieldInfo($key) 2] lappend antry [format "%-30s # %s" $field $meaning] } else { lappend antry $field } } set s [join $antry "\n "] puts "\n $s" } }