1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 2 3<html> 4 <head> 5 <meta name="generator" content="HTML Tidy, see www.w3.org"> 6 <title>Using Programs To Get Printcap Information</title> 7 <meta name="GENERATOR" content= 8 "Modular DocBook HTML Stylesheet Version 1.7"> 9 <link rel="HOME" title=" LPRng Reference Manual" href= 10 "index.htm"> 11 <link rel="UP" title="Printcap Database " href= 12 "printcapref.htm"> 13 <link rel="PREVIOUS" title= 14 "Management Strategies for Large Installations" href= 15 "x6118.htm"> 16 <link rel="NEXT" title="Lexmark Printers" href="x6228.htm"> 17 </head> 18 19 <body class="SECT1" bgcolor="#FFFFFF" text="#000000" link= 20 "#0000FF" vlink="#840084" alink="#0000FF"> 21 <div class="NAVHEADER"> 22 <table summary="Header navigation table" width="100%" border= 23 "0" cellpadding="0" cellspacing="0"> 24 <tr> 25 <th colspan="3" align="center">LPRng Reference Manual: 5 26 Sep 2003 (For LPRng-3.8.22)</th> 27 </tr> 28 29 <tr> 30 <td width="10%" align="left" valign="bottom"><a href= 31 "x6118.htm" accesskey="P">Prev</a></td> 32 33 <td width="80%" align="center" valign="bottom">Chapter 34 12. Printcap Database</td> 35 36 <td width="10%" align="right" valign="bottom"><a href= 37 "x6228.htm" accesskey="N">Next</a></td> 38 </tr> 39 </table> 40 <hr align="LEFT" width="100%"> 41 </div> 42 43 <div class="SECT1"> 44 <h1 class="SECT1"><a name="SECNIS">12.18. Using Programs To 45 Get Printcap Information</a></h1> 46 47 <p>In the <tt class="FILENAME">lpd.conf</tt> file you can 48 specify:</p> 49 50 <div class="INFORMALEXAMPLE"> 51 <a name="AEN6130"></a> 52<pre class="SCREEN"> 53 printcap_path=|program 54</pre> 55 </div> 56 This will cause the <b class="APPLICATION">LPRng</b> software 57 to execute the specified program, which should then provide 58 the printcap information. The program is invoked with the 59 standard filter options, and has the name of the printcap 60 entry provided on <acronym class="ACRONYM">STDIN</acronym>. 61 The filter should supply the printcap information on <var 62 class="LITERAL">stdout</var> and exit with a 0 (success) 63 error code. By convention, the printcap name 'all' requests a 64 printcap entry that lists all printers.<br> 65 <br> 66 67 <p>This technique has been used to interface to the Sun 68 Microsystem NIS and NIS+ databases with great success. By 69 having the invoked program a simple shell script or front end 70 to the <var class="LITERAL">nismatch</var> or <var class= 71 "LITERAL">ypmatch</var> programs, the complexity of 72 incorporating vendor specific code is avoided.</p> 73 74 <div class="SECT2"> 75 <h2 class="SECT2"><a name="AEN6138">12.18.1. How to use NIS 76 and <b class="APPLICATION">LPRng</b></a></h2> 77 78 <p>This note is based on material sent to the <a href= 79 "maillist.htm">lprng@lprng.com</a> mailing list by Paul 80 Haldane <code class="EMAIL"><<a href= 81 "mailto:paul@ucs.ed.ac.uk">paul@ucs.ed.ac.uk</a>></code>.</p> 82 83 <p>We generally don't use NIS for printcap files (we've 84 moved to hesiod) but I can show you what we've done in the 85 past.</p> 86 87 <p>The input to NIS is a normal printcap file:</p> 88 89 <div class="INFORMALEXAMPLE"> 90 <a name="AEN6146"></a> 91<pre class="SCREEN"> 92 # Classical printcap entry 93 lp23a|lp23|lp|main printhost printer - KB, EUCS front Door:\ 94 :lp=lp23a@printhost:\ 95 :sd=/var/spool/lpr/lp23a: 96 97 #lprng printcap entry 98 lplabel|lpl|TEST - Labels printer: 99 :lp=:rm=printhost:rp=lplabel: 100 :sd=/var/spool/lpr/lplabel: 101 :rg=lpadm:mx=1: 102</pre> 103 </div> 104 <br> 105 <br> 106 107 <p>To build the NIS printcap.byname map we add the 108 following to the NIS makefile (along the other bits and 109 pieces that the makefile needs to know about a new 110 map).</p> 111 112 <div class="INFORMALEXAMPLE"> 113 <a name="AEN6149"></a> 114<pre class="SCREEN"> 115 PRINTCAP=${sysconfdir}/printcap 116 # warning : [ ] is actually [<space><tab>] in the script 117 printcap.time: $(PRINTCAP) Makefile 118 if [ -f $(PRINTCAP) ]; then \ 119 sed < $(PRINTCAP) \ 120 -e 's/[ ][ ]*$$//' -e '/\\$$/s/\\$$/ /' \ 121 | awk '$$1 ~ /^#/{next;} $$1 ~ /^[:|]/ {printf "%s", $$0; next;} \ 122 {printf "\n%s", $$0 }' \ 123 | sed -e 's/[ ]*:[ ]*:/:/g' -e 's/[ ]*|[ ]*/|/g' \ 124 -e '/^[ ]*$$/d' > .printcap.$$$$; \ 125 cat .printcap.$$$$; \ 126 if [ $$? = 0 -a -s .printcap.$$$$ ]; then \ 127 awk <.printcap.$$$$ '{ FS=":"; OFS="\t"; } { \ 128 n = split($$1, names, "|"); \ 129 for (i=1; i<=n; i++) \ 130 if (length(names[i]) > 0 \ 131 && names[i] !~ /[ \t]/) \ 132 print names[i], $$0; \ 133 }' | $(MAKEDBM) - $(YPDBDIR)/$(DOM)/printcap.byname; \ 134 awk <.printcap.$$$$ '{ FS=":"; OFS="\t"; } { \ 135 n = split($$1, names, "|"); \ 136 if (n && length(names[1]) > 0 && names[1] !~ /[ \t]/) \ 137 print names[1], $$0; \ 138 }' | $(MAKEDBM) - $(YPDBDIR)/$(DOM)/printcap.bykey; \ 139 rm -f .printcap.$$$$; \ 140 touch printcap.time; echo "updated printcap"; \ 141 fi \ 142 fi 143 @if [ ! $(NOPUSH) -a -f $(PRINTCAP) ]; then \ 144 $(YPPUSH) printcap.byname; \ 145 $(YPPUSH) printcap.bykey; \ 146 touch printcap.time; echo "pushed printcap"; \ 147 fi 148</pre> 149 </div> 150 <br> 151 <br> 152 153 <p>To specify that you want YP database rather than file 154 access, use the following entry in your <tt class= 155 "FILENAME">/etc/lpd.conf</tt> file:</p> 156 157 <div class="INFORMALEXAMPLE"> 158 <a name="AEN6153"></a> 159<pre class="SCREEN"> 160 printcap_path |/usr/local/libexec/pcfilter 161</pre> 162 </div> 163 <br> 164 <br> 165 166 <p>Put the following shell script in 167 /usr/local/libexec/pcfilter</p> 168 169 <div class="INFORMALEXAMPLE"> 170 <a name="AEN6156"></a> 171<pre class="SCREEN"> 172 #!/bin/sh 173 #/usr/local/libexec/filters/pcfilter 174 read key 175 # specify the full pathname to the ypmatch program 176 # the location depends on the version of Solaris or your 177 # system install 178 /full/pathname/to/ypmatch "$key" printcap.byname 179</pre> 180 </div> 181 <br> 182 <br> 183 184 <p>You can test this by using:</p> 185 186 <div class="INFORMALEXAMPLE"> 187 <a name="AEN6159"></a> 188<pre class="SCREEN"> 189 <samp class="PROMPT">h4: {314} #</samp> <kbd class= 190"USERINPUT">lpc client pr</kbd> 191 pr 192 :lp=pr@server 193 <samp class="PROMPT">h4: {315} #</samp> <kbd class= 194"USERINPUT">lpc server pr</kbd> 195 pr 196 :lp=pr@server 197</pre> 198 </div> 199 <br> 200 <br> 201 </div> 202 203 <div class="SECT2"> 204 <h2 class="SECT2"><a name="AEN6165">12.18.2. How to use NIS 205 and <b class="APPLICATION">LPRng</b> - Sven 206 Rudolph</a></h2> 207 208 <div class="INFORMALEXAMPLE"> 209 <a name="AEN6169"></a> 210<pre class="SCREEN"> 211 Date: Wed, 11 Sep 1996 00:11:02 +0200 212 From: Sven Rudolph <sr1@os.inf.tu-dresden.de> 213 To: lprng@lprng.com 214 Subject: Using :oh=server: with NIS 215</pre> 216 </div> 217 <br> 218 <br> 219 220 <p>When I use a cluster-wide printcap, I want the entries 221 for each printer to appear, e.g.:</p> 222 223 <div class="INFORMALEXAMPLE"> 224 <a name="AEN6172"></a> 225<pre class="SCREEN"> 226 ---------- start of printcap snippet 227 lp1 228 :lp=lp1@server 229 lp2 230 :lp=lp2@server 231 lp1 232 :server:oh=servername 233 :sd=/var/spool/lpd/lp1 234 :lp=/dev/lp1 235 :mx=0 236 ---------- end of printcap snippet 237</pre> 238 </div> 239 <br> 240 <br> 241 242 <p>When I create a NIS map out of this the printer name is 243 used as a key and must be unique. The NIS makedbm will drop 244 all but the last entry for each printer. This makes the 245 printer on the clients unavailable. I solved this by a hack 246 where the second entry is called lp1.server and the NIS 247 client script has to request the right entry.</p> 248 249 <ol type="1"> 250 <li> 251 <p>Assumptions</p> 252 253 <p>Perl is available at the YP server in <tt class= 254 "COMMAND">/usr/bin/perl</tt>. A Bourne Shell is 255 available at all clients in <tt class= 256 "COMMAND">/bin/sh</tt> The printcap that is to be 257 exported is in <tt class="FILENAME">/etc/printcap</tt>. 258 The printcap is written in the new format. In the 259 examples the printer is called lp1.</p> 260 </li> 261 262 <li> 263 <p>Add the following to your YP <tt class= 264 "FILENAME">Makefile</tt> (<tt class= 265 "FILENAME">/var/yp/Makefile</tt>) on the YP server 266 (these lines are for Debian GNU/Linux, other systems 267 might require other modifications):</p> 268 269 <div class="INFORMALEXAMPLE"> 270 <a name="AEN6186"></a> 271<pre class="SCREEN"> 272 ---------- start of /var/yp/Makefile snippet 273 PRINTCAP = /etc/printcap 274 printcap: $(PRINTCAP) 275 @echo "Updating $@..." 276 $(CAT) $(PRINTCAP) | \ 277 /usr/lib/yp/normalize_printcap | $(DBLOAD) -i $(PRINTCAP) \ 278 -o $(YPMAPDIR)/$@ - $@ 279 @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi 280 @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi 281 ---------- end of /var/yp/Makefile snippet 282</pre> 283 </div> 284 <br> 285 <br> 286 </li> 287 288 <li> 289 <p>Install the programs <b class= 290 "APPLICATION">match_printcap</b> and <b class= 291 "APPLICATION">normalize_printcap</b> in the <tt class= 292 "FILENAME">/usr/lib/yp</tt> directory; <b class= 293 "APPLICATION">normalize_printcap</b> is only required 294 on the YP server. The <b class= 295 "APPLICATION">normalize_printcap</b> processes only the 296 <b class="APPLICATION">LPRng</b> printcap format.</p> 297 298 <div class="INFORMALEXAMPLE"> 299 <a name="AEN6196"></a> 300<pre class="SCREEN"> 301 ---------- start of /usr/lib/yp/normalize_printcap 302 #! /usr/bin/perl 303 $debug = 0; 304 $line = ""; 305 $new = ""; 306 while (<>) { 307 chomp; 308 next if ( /^\s*\#.*/ ); 309 s/^\s*$//; 310 next if ( $_ eq '' ); 311 print "new: " . $_ . "\n" if $debug;; 312 if (/^\s/) { # continuation line 313 $line = $line.$_; 314 print "continued: $line\n" if $debug; 315 next; 316 } else { 317 $line =~ s/\s+\:/:/g; 318 $line =~ s/\:\s+/:/g; 319 $line =~ s/\:\s*\:/:/g; 320 print "line: $line\n" if $debug; 321 push(@lines, $line) if $line; 322 $line = $_; 323 } 324 } 325 $line =~ s/\s+\:/:/g; 326 $line =~ s/\:\s+/:/g; 327 $line =~ s/\:\s*\:/:/g; 328 push(@lines,$line) if $line; 329 @lines = sort(@lines); 330 foreach $line (@lines) { 331 ($printers) = split(/\:/,$line); 332 @printers = split(/\|/,$printers); 333 foreach $printer (@printers) { 334 $num{$printer}++; 335 push(@allprinters,$printer); 336 print "allprinters: @allprinters\n" if $debug; 337 print $printer."_".$num{$printer}."\t$line\n"; 338 } 339 } 340 @pr = keys %num; 341 print "printers @pr\n" if $debug; 342 if ($#allprinters >=0) { 343 print "all_1\tall:all=".join(",",@pr)."\n"; 344 } 345 ---------- end of /usr/lib/yp/normalize_printcap 346</pre> 347 </div> 348 <br> 349 <br> 350 351 <p>The result of processing the sample printcap file 352 is:</p> 353 354 <div class="INFORMALEXAMPLE"> 355 <a name="AEN6199"></a> 356<pre class="SCREEN"> 357 lp1_1 lp1:lp=lp1@server 358 lp1_2 lp1:server:oh=servername:sd=/var/spool/lpd/lp1:lp=/dev/lp1:mx=0 359 lp2_1 lp2:lp=lp2@server 360 all_1 all:all=lp1,lp2 361</pre> 362 </div> 363 <br> 364 <br> 365 366 <p>Observe that each of the real printer entries has a 367 key consisting of the printer name with a numerical 368 suffix. This leads to the following method of 369 extracting the printcap information using <var class= 370 "LITERAL">ypmatch</var>:</p> 371 372 <div class="INFORMALEXAMPLE"> 373 <a name="AEN6203"></a> 374<pre class="SCREEN"> 375 ---------- start of /usr/lib/yp/match_printcap 376 #!/bin/sh 377 read p 378 n=1 379 # specify the full pathname to ypmatch - this depends on your 380 # OS version and installation 381 while /full/pathname/to/ypmatch "${p}_${n}" printcap 2>/dev/null; do 382 n=`expr $n + 1` 383 done 384 ---------- end of /usr/lib/yp/match_printcap 385</pre> 386 </div> 387 <br> 388 <br> 389 </li> 390 391 <li> 392 <p>Now test the YP arrangement:</p> 393 394 <div class="INFORMALEXAMPLE"> 395 <a name="AEN6207"></a> 396<pre class="SCREEN"> 397 <samp class="PROMPT">h4: {316} #</samp> cd /var/yp; make 398 # this should create the printcap map 399 <samp class="PROMPT">h4: {317} #</samp> ypcat printcap 400 # should provide the whole normalized printcap 401 <samp class= 402"PROMPT">h4: {318} #</samp> echo lp1 |/usr/lib/yp/match_printcap 403 # yields lp1 printcap 404</pre> 405 </div> 406 <br> 407 <br> 408 </li> 409 410 <li> 411 <p>Modify the <var class="LITERAL">printcap_path</var> 412 entry in the <tt class="FILENAME">lpd.conf</tt> 413 file:</p> 414 415 <div class="INFORMALEXAMPLE"> 416 <a name="AEN6216"></a> 417<pre class="SCREEN"> 418 printcap_path=|/usr/lib/yp/match_printcap 419</pre> 420 </div> 421 <br> 422 <br> 423 </li> 424 425 <li> 426 <p>Test the use of the printcap path entry:</p> 427 428 <div class="INFORMALEXAMPLE"> 429 <a name="AEN6220"></a> 430<pre class="SCREEN"> 431 <samp class= 432"PROMPT">h4: {319} #</samp> lpc client lp1 # shows the printcap for lp1 433 <samp class= 434"PROMPT">h4: {320} #</samp> lpc server lp1 # shows the printcap for lp1 435</pre> 436 </div> 437 <br> 438 <br> 439 </li> 440 441 <li> 442 <p>Restart the lpd server and check to see that it 443 accesses the right printcap information. Use the same 444 <b class="APPLICATION">lpq</b> command, and then try 445 <tt class="COMMAND">lpc printcap lp1</tt>.</p> 446 </li> 447 </ol> 448 <br> 449 <br> 450 </div> 451 </div> 452 453 <div class="NAVFOOTER"> 454 <hr align="LEFT" width="100%"> 455 456 <table summary="Footer navigation table" width="100%" border= 457 "0" cellpadding="0" cellspacing="0"> 458 <tr> 459 <td width="33%" align="left" valign="top"><a href= 460 "x6118.htm" accesskey="P">Prev</a></td> 461 462 <td width="34%" align="center" valign="top"><a href= 463 "index.htm" accesskey="H">Home</a></td> 464 465 <td width="33%" align="right" valign="top"><a href= 466 "x6228.htm" accesskey="N">Next</a></td> 467 </tr> 468 469 <tr> 470 <td width="33%" align="left" valign="top">Management 471 Strategies for Large Installations</td> 472 473 <td width="34%" align="center" valign="top"><a href= 474 "printcapref.htm" accesskey="U">Up</a></td> 475 476 <td width="33%" align="right" valign="top">Lexmark 477 Printers</td> 478 </tr> 479 </table> 480 </div> 481 </body> 482</html> 483 484