]> arthur.barton.de Git - netatalk.git/blob - etc/papd/main.c
a98009cd93bc5d375fa66986f081f84dee270259
[netatalk.git] / etc / papd / main.c
1 /*
2  * Copyright (c) 1990,1995 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include <sys/param.h>
11 #include <sys/types.h>
12 #include <sys/time.h>
13 #include <sys/uio.h>
14 #if defined( sun ) && defined( __svr4__ )
15 #include </usr/ucbinclude/sys/file.h>
16 #else sun __svr4__
17 #include <sys/file.h>
18 #endif sun __svr4__
19 #include <sys/socket.h>
20 #include <sys/syslog.h>
21 #include <sys/wait.h>
22 #include <errno.h>
23
24 #include <string.h>
25 #include <signal.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <netdb.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31
32 #include <netatalk/endian.h>
33 #include <netatalk/at.h>
34 #include <atalk/compat.h>
35 #include <atalk/atp.h>
36 #include <atalk/pap.h>
37 #include <atalk/paths.h>
38 #include <atalk/util.h>
39
40 #include "printer.h"
41
42 #define _PATH_PAPDPPDFILE       ".ppd"
43
44 #define PIPED_STATUS    "status: print spooler processing job"
45
46 struct printer  defprinter;
47 struct printer  *printers = NULL;
48
49 int             debug = 0;
50 char            *conffile = _PATH_PAPDCONF;
51 char            *printcap = _PATH_PAPDPRINTCAP;
52 unsigned char   connid, quantum, sock, oquantum = PAP_MAXQUANTUM;
53 char            *cannedstatus = PIPED_STATUS;
54 struct printer  *printer = NULL;
55 char            *version = VERSION;
56 static char      *pidfile = _PATH_PAPDLOCK;
57
58 char            *uamlist;
59 char            *uampath = _PATH_PAPDUAMPATH;
60
61 /* this only needs to be used by the server process */
62 static void papd_exit(const int i)
63 {
64   server_unlock(pidfile);
65   auth_unload();
66   exit(i);
67 }
68
69 #if !defined( ibm032 ) && !defined( _IBMR2 )
70     void
71 #endif ibm032 _IBMR2
72 die( n )
73     int                 n;
74 {
75     struct printer      *pr;
76
77     for ( pr = printers; pr; pr = pr->p_next ) {
78         if ( pr->p_flags & P_REGISTERED ) {
79             if ( nbp_unrgstr( pr->p_name, pr->p_type, pr->p_zone ) < 0 ) {
80                 syslog( LOG_ERR, "can't unregister %s:%s@%s\n", pr->p_name,
81                         pr->p_type, pr->p_zone );
82                 papd_exit( n + 1 );
83             }
84             syslog( LOG_ERR, "unregister %s:%s@%s\n", pr->p_name, pr->p_type,
85                     pr->p_zone );
86         }
87     }
88     papd_exit( n );
89 }
90
91 #if !defined( ibm032 ) && !defined( _IBMR2 )
92     void
93 #endif ibm032 _IBMR2
94 reap()
95 {
96     int         status;
97     int         pid;
98
99     while (( pid = wait3( &status, WNOHANG, 0 )) > 0 ) {
100         if ( WIFEXITED( status )) {
101             if ( WEXITSTATUS( status )) {
102                 syslog( LOG_ERR, "child %d exited with %d", pid,
103                         WEXITSTATUS( status ));
104             } else {
105                 syslog( LOG_INFO, "child %d done", pid );
106             }
107         } else {
108             if ( WIFSIGNALED( status )) {
109                 syslog( LOG_ERR, "child %d killed with %d", pid,
110                         WTERMSIG( status ));
111             } else {
112                 syslog( LOG_ERR, "child %d died", pid );
113             }
114         }
115     }
116     return;
117 }
118
119 char            rbuf[ 255 + 1 + 8 ];
120
121 main( ac, av )
122     int         ac;
123     char        **av;
124 {
125     extern char         *optarg;
126     extern int          optind;
127
128     ATP                 atp;
129     struct atp_block    atpb;
130     struct sockaddr_at  sat;
131     struct sigaction    sv;
132     struct iovec        iov;
133     fd_set              fdset;
134     struct printer      *pr;
135     char                *p, hostname[ MAXHOSTNAMELEN ];
136     char                cbuf[ 8 ];
137     int                 c;
138
139     if ( gethostname( hostname, sizeof( hostname )) < 0 ) {
140         perror( "gethostname" );
141         exit( 1 );
142     }
143     if (( p = strchr( hostname, '.' )) != 0 ) {
144         *p = '\0';
145     }
146     if (( defprinter.p_name = (char *)malloc( strlen( hostname ) + 1 ))
147             == NULL ) {
148         perror( "malloc" );
149         exit( 1 );
150     }
151     strcpy( defprinter.p_name, hostname );
152     defprinter.p_type = "LaserWriter";
153     defprinter.p_zone = "*";
154     memset(&defprinter.p_addr, 0, sizeof(defprinter.p_addr));
155     defprinter.p_ppdfile = _PATH_PAPDPPDFILE;
156 #ifdef __svr4__
157     defprinter.p_flags = P_PIPED;
158     defprinter.p_printer = "/usr/bin/lp -T PS";
159 #else
160     defprinter.p_flags = P_SPOOLED;
161     defprinter.p_printer = "lp";
162 #endif
163     defprinter.p_operator = "operator";
164     defprinter.p_spool = _PATH_PAPDSPOOLDIR;
165 #ifdef ABS_PRINT
166     defprinter.p_role = NULL;
167     defprinter.p_srvid = 0;
168 #endif ABS_PRINT
169     defprinter.p_pagecost = 200;                /* default cost */
170     defprinter.p_pagecost_msg = NULL;
171     defprinter.p_lock = "lock";
172
173     while (( c = getopt( ac, av, "adf:p:P:" )) != EOF ) {
174         switch ( c ) {
175         case 'a' :              /* for compatibility with old papd */
176             break;
177
178         case 'd' :              /* debug */
179             debug++;
180             break;
181
182         case 'f' :              /* conffile */
183             conffile = optarg;
184             break;
185
186         case 'p' :              /* printcap */
187             printcap = optarg;
188             break;
189
190         case 'P' :
191             pidfile = optarg;
192             break;
193
194         default :
195             fprintf( stderr,
196                     "Usage:\t%s [ -d ] [ -f conffile ] [ -p printcap ]\n",
197                     *av );
198             exit( 1 );
199         }
200     }
201
202     getprinters( conffile );
203
204     switch (server_lock("papd", pidfile, debug)) {
205     case 0: /* open a couple things again in the child */
206       if ((c = open("/", O_RDONLY)) >= 0) {
207         dup2(c, 1);
208         dup2(c, 2);
209       }
210       break;
211     case -1:
212       exit(1);
213     default:
214       exit(0);
215     }      
216
217     /*
218      * Start logging.
219      */
220     if (( p = strrchr( av[ 0 ], '/' )) == NULL ) {
221         p = av[ 0 ];
222     } else {
223         p++;
224     }
225 #ifdef ultrix
226     openlog( p, LOG_PID );
227 #else ultrix
228     openlog( p, LOG_NDELAY|LOG_PID, LOG_LPR );
229 #endif ultrix
230
231     syslog( LOG_INFO, "restart (%s)", version );
232
233     for ( pr = printers; pr; pr = pr->p_next ) {
234         if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) < 0 ) {
235             syslog( LOG_ERR, "printcap problem: %s", pr->p_printer );
236         }
237         if (( pr->p_atp = atp_open( ATADDR_ANYPORT, &pr->p_addr )) == NULL ) {
238             syslog( LOG_ERR, "atp_open: %m" );
239             papd_exit( 1 );
240         }
241         if ( nbp_rgstr( atp_sockaddr( pr->p_atp ), pr->p_name, pr->p_type,
242                 pr->p_zone ) < 0 ) {
243             syslog( LOG_ERR, "can't register %s:%s@%s", pr->p_name, pr->p_type,
244                     pr->p_zone );
245             die( 1 );
246         }
247         if ( pr->p_flags & P_AUTH ) {
248                 syslog( LOG_INFO, "Authentication enabled: %s", pr->p_name );
249         }
250         else {
251                 syslog( LOG_INFO, "Authentication disabled: %s", pr->p_name );
252         }
253         syslog( LOG_INFO, "register %s:%s@%s", pr->p_name, pr->p_type,
254                 pr->p_zone );
255         pr->p_flags |= P_REGISTERED;
256     }
257
258     memset(&sv, 0, sizeof(sv));
259     sv.sa_handler = die;
260     sigemptyset( &sv.sa_mask );
261     sv.sa_flags = SA_RESTART;
262     if ( sigaction( SIGTERM, &sv, 0 ) < 0 ) {
263         syslog( LOG_ERR, "sigaction: %m" );
264         papd_exit( 1 );
265     }
266
267     sv.sa_handler = reap;
268     sigemptyset( &sv.sa_mask );
269     sv.sa_flags = SA_RESTART;
270     if ( sigaction( SIGCHLD, &sv, 0 ) < 0 ) {
271         syslog( LOG_ERR, "sigaction: %m" );
272         papd_exit( 1 );
273     }
274
275     /*
276      * Load UAMS
277      */
278     auth_load(uampath, uamlist);
279
280     /*
281      * Begin accepting connections.
282      */
283     FD_ZERO( &fdset );
284     for (;;) {
285         for ( pr = printers; pr; pr = pr->p_next ) {
286             FD_SET( atp_fileno( pr->p_atp ), &fdset );
287         }
288         if (( c = select( FD_SETSIZE, &fdset, 0, 0, 0 )) < 0 ) {
289             if ( errno == EINTR ) {
290                 continue;
291             }
292             syslog( LOG_ERR, "select: %m" );
293             papd_exit( 1 );
294         }
295
296         for ( pr = printers; pr; pr = pr->p_next ) {
297             if ( FD_ISSET( atp_fileno( pr->p_atp ), &fdset )) {
298                 int             err = 0;
299
300                 bzero( &sat, sizeof( struct sockaddr_at ));
301 #ifdef BSD4_4
302                 sat.sat_len = sizeof( struct sockaddr_at );
303 #endif BSD4_4
304                 sat.sat_family = AF_APPLETALK;
305                 sat.sat_addr.s_net = ATADDR_ANYNET;
306                 sat.sat_addr.s_node = ATADDR_ANYNODE;
307                 sat.sat_port = ATADDR_ANYPORT;
308                 /* do an atp_rsel(), to prevent hangs */
309                 if (( c = atp_rsel( pr->p_atp, &sat, ATP_TREQ )) != ATP_TREQ ) {
310                     continue;
311                 }
312                 atpb.atp_saddr = &sat;
313                 atpb.atp_rreqdata = cbuf;
314                 atpb.atp_rreqdlen = sizeof( cbuf );
315                 if ( atp_rreq( pr->p_atp, &atpb ) < 0 ) {
316                     syslog( LOG_ERR, "atp_rreq: %m" );
317                     continue;
318                 }
319
320                 /* should check length of req buf */
321
322                 switch( cbuf[ 1 ] ) {
323                 case PAP_OPEN :
324                     connid = (unsigned char)cbuf[ 0 ];
325                     sock = (unsigned char)cbuf[ 4 ];
326                     quantum = (unsigned char)cbuf[ 5 ];
327                     rbuf[ 0 ] = cbuf[ 0 ];
328                     rbuf[ 1 ] = PAP_OPENREPLY;
329                     rbuf[ 2 ] = rbuf[ 3 ] = 0;
330
331                     if (( pr->p_flags & P_SPOOLED ) && rprintcap( pr ) != 0 ) {
332                         syslog( LOG_ERR, "printcap problem: %s",
333                                 pr->p_printer );
334                         rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
335                         err = 1;
336                     }
337
338                     /*
339                      * If this fails, we've run out of sockets. Rather than
340                      * just die(), let's try to continue. Maybe some sockets
341                      * will close, and we can continue;
342                      */
343                     if (( atp = atp_open( ATADDR_ANYPORT, 
344                                           &pr->p_addr)) == NULL ) {
345                         syslog( LOG_ERR, "atp_open: %m" );
346                         rbuf[ 2 ] = rbuf[ 3 ] = 0xff;
347                         err = 1;
348                     }
349                     rbuf[ 4 ] = atp_sockaddr( atp )->sat_port;
350                     rbuf[ 5 ] = oquantum;
351                     rbuf[ 6 ] = rbuf[ 7 ] = 0;
352
353                     iov.iov_base = rbuf;
354                     iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
355                     atpb.atp_sresiov = &iov;
356                     atpb.atp_sresiovcnt = 1;
357                     /*
358                      * This may error out if we lose a route, so we won't die().
359                      */
360                     if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
361                         syslog( LOG_ERR, "atp_sresp: %m" );
362                         continue;
363                     }
364
365                     if ( err ) {
366                         continue;
367                     }
368
369                     switch ( c = fork()) {
370                     case -1 :
371                         syslog( LOG_ERR, "fork: %m" );
372                         continue;
373
374                     case 0 : /* child */
375                         printer = pr;
376
377                         if (( printer->p_flags & P_SPOOLED ) &&
378                                 chdir( printer->p_spool ) < 0 ) {
379                             syslog( LOG_ERR, "chdir %s: %m", printer->p_spool );
380                             exit( 1 );
381                         }
382
383                         sv.sa_handler = SIG_DFL;
384                         sigemptyset( &sv.sa_mask );
385                         sv.sa_flags = SA_RESTART;
386                         if ( sigaction( SIGTERM, &sv, 0 ) < 0 ) {
387                             syslog( LOG_ERR, "sigaction: %m" );
388                             exit( 1 );
389                         }
390
391                         for ( pr = printers; pr; pr = pr->p_next ) {
392                             atp_close( pr->p_atp );
393                         }
394                         sat.sat_port = sock;
395                         if ( session( atp, &sat ) < 0 ) {
396                             syslog( LOG_ERR, "bad session" );
397                             exit( 1 );
398                         }
399                         exit( 0 );
400                         break;
401
402                     default : /* parent */
403                         syslog( LOG_INFO, "child %d for \"%s\" from %u.%u",
404                                 c, pr->p_name, ntohs( sat.sat_addr.s_net ),
405                                 sat.sat_addr.s_node);
406                         atp_close( atp );
407                     }
408                     break;
409
410                 case PAP_SENDSTATUS :
411                     rbuf[ 0 ] = 0;
412                     rbuf[ 1 ] = PAP_STATUS;
413                     rbuf[ 2 ] = rbuf[ 3 ] = 0;
414                     rbuf[ 4 ] = rbuf[ 5 ] = 0;
415                     rbuf[ 6 ] = rbuf[ 7 ] = 0;
416
417                     iov.iov_base = rbuf;
418                     iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
419                     atpb.atp_sresiov = &iov;
420                     atpb.atp_sresiovcnt = 1;
421                     /*
422                      * This may error out if we lose a route, so we won't die().
423                      */
424                     if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
425                         syslog( LOG_ERR, "atp_sresp: %m" );
426                     }
427                     break;
428
429                 default :
430                     syslog( LOG_ERR, "Bad request from %u.%u!",
431                             ntohs( sat.sat_addr.s_net ), sat.sat_addr.s_node );
432                     continue;
433                     break;
434                 }
435
436 #ifdef notdef
437                 /*
438                  * Sometimes the child process will send its first READ
439                  * before the parent has sent the OPEN REPLY.  Moving this
440                  * code into the OPEN/STATUS switch fixes this problem.
441                  */
442                 iov.iov_base = rbuf;
443                 iov.iov_len = 8 + getstatus( pr, &rbuf[ 8 ] );
444                 atpb.atp_sresiov = &iov;
445                 atpb.atp_sresiovcnt = 1;
446                 /*
447                  * This may error out if we lose a route, so we won't die().
448                  */
449                 if ( atp_sresp( pr->p_atp, &atpb ) < 0 ) {
450                     syslog( LOG_ERR, "atp_sresp: %m" );
451                 }
452 #endif notdef
453             }
454         }
455     }
456 }
457
458 /*
459  * We assume buf is big enough for 255 bytes of data and a length byte.
460  */
461     int
462 getstatus( pr, buf )
463     struct printer      *pr;
464     char                *buf;
465 {
466     char                path[ MAXPATHLEN ];
467     int                 fd = -1, rc;
468
469     if ( pr->p_flags & P_SPOOLED && ( pr->p_spool != NULL )) {
470         strcpy( path, pr->p_spool );
471         strcat( path, "/status" );
472         fd = open( path, O_RDONLY);
473     }
474
475     if (( pr->p_flags & P_PIPED ) || ( fd < 0 )) {
476         *buf = strlen( cannedstatus );
477         strncpy( &buf[ 1 ], cannedstatus, *buf );
478         return( *buf + 1 );
479     } else {
480         if (( rc = read( fd, &buf[ 1 ], 255 )) < 0 ) {
481             rc = 0;
482         }
483         close( fd );
484         if ( rc && buf[ rc ] == '\n' ) {        /* remove trailing newline */
485             rc--;
486         }
487         *buf = rc;
488         return( rc + 1 );
489     }
490 }
491
492 char    *pgetstr();
493 char    *getpname();
494
495 getprinters( cf )
496     char        *cf;
497 {
498     char                buf[ 1024 ], area[ 1024 ], *a, *p, *name, *type, *zone;
499     struct printer      *pr;
500     int                 c;
501
502     while (( c = getprent( cf, buf )) > 0 ) {
503         a = area;
504         /*
505          * Get the printer's nbp name.
506          */
507         if (( p = getpname( &a )) == NULL ) {
508             fprintf( stderr, "No printer name\n" );
509             exit( 1 );
510         }
511
512         if (( pr = (struct printer *)malloc( sizeof( struct printer )))
513                 == NULL ) {
514             perror( "malloc" );
515             exit( 1 );
516         }
517         bzero( pr, sizeof( struct printer ));
518
519         name = defprinter.p_name;
520         type = defprinter.p_type;
521         zone = defprinter.p_zone;
522         if ( nbp_name( p, &name, &type, &zone )) {
523             fprintf( stderr, "Can't parse \"%s\"\n", name );
524             exit( 1 );
525         }
526         if ( name != defprinter.p_name ) {
527             if (( pr->p_name = (char *)malloc( strlen( name ) + 1 )) == NULL ) {
528                 perror( "malloc" );
529                 exit( 1 );
530             }
531             strcpy( pr->p_name, name );
532         } else {
533             pr->p_name = name;
534         }
535         if ( type != defprinter.p_type ) {
536             if (( pr->p_type = (char *)malloc( strlen( type ) + 1 )) == NULL ) {
537                 perror( "malloc" );
538                 exit( 1 );
539             }
540             strcpy( pr->p_type, type );
541         } else {
542             pr->p_type = type;
543         }
544         if ( zone != defprinter.p_zone ) {
545             if (( pr->p_zone = (char *)malloc( strlen( zone ) + 1 )) == NULL ) {
546                 perror( "malloc" );
547                 exit( 1 );
548             }
549             strcpy( pr->p_zone, zone );
550         } else {
551             pr->p_zone = zone;
552         }
553
554         if ( pnchktc( cf ) != 1 ) {
555             fprintf( stderr, "Bad papcap entry\n" );
556             exit( 1 );
557         }
558
559         /*
560          * Get PPD file.
561          */
562         if (( p = pgetstr( "pd", &a )) == NULL ) {
563             pr->p_ppdfile = defprinter.p_ppdfile;
564         } else {
565             if (( pr->p_ppdfile = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
566                 perror( "malloc" );
567                 exit( 1 );
568             }
569             strcpy( pr->p_ppdfile, p );
570         }
571
572         /*
573          * Get lpd printer name.
574          */
575         if (( p = pgetstr( "pr", &a )) == NULL ) {
576             pr->p_printer = defprinter.p_printer;
577             pr->p_flags = defprinter.p_flags;
578         } else {
579             if ( *p == '|' ) {
580                 p++;
581                 pr->p_flags = P_PIPED;
582             } else {
583                 pr->p_flags = P_SPOOLED;
584             }
585             if (( pr->p_printer = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
586                 perror( "malloc" );
587                 exit( 1 );
588             }
589             strcpy( pr->p_printer, p );
590         }
591
592         /*
593          * Do we want authenticated printing?
594          */
595         if ( pgetflag( "ca", &a ) == 1 ) {
596             pr->p_flags |= P_AUTH;
597             pr->p_flags |= P_AUTH_CAP;
598         }
599         if ( pgetflag( "sp", &a ) == 1 ) {
600             pr->p_flags |= P_AUTH;
601             pr->p_flags |= P_AUTH_PSSP;
602         }
603
604         if ((p = pgetstr("am", &a)) != NULL ) {
605                 if ((uamlist = (char *)malloc(strlen(p)+1)) == NULL ) {
606                         perror("malloc");
607                         exit(1);
608                 }
609                 strcpy(uamlist, p);
610         }
611
612         if ( pr->p_flags & P_SPOOLED ) {
613             /*
614              * Get operator name.
615              */
616             if (( p = pgetstr( "op", &a )) == NULL ) {
617                 pr->p_operator = defprinter.p_operator;
618             } else {
619                 if (( pr->p_operator = (char *)malloc( strlen( p ) + 1 ))
620                         == NULL ) {
621                     perror( "malloc" );
622                     exit( 1 );
623                 }
624                 strcpy( pr->p_operator, p );
625             }
626         }
627
628         /* get printer's appletalk address. */
629         if (( p = pgetstr( "pa", &a )) == NULL ) 
630             memcpy(&pr->p_addr, &defprinter.p_addr, sizeof(pr->p_addr));
631         else 
632             atalk_aton(p, &pr->p_addr);
633
634         pr->p_next = printers;
635         printers = pr;
636     }
637     if ( c == 0 ) {
638         endprent();
639     } else {                    /* No capability file, do default */
640         printers = &defprinter;
641     }
642 }
643
644 rprintcap( pr )
645     struct printer      *pr;
646 {
647     char                buf[ 1024 ], area[ 1024 ], *a, *p;
648     int                 c;
649
650     /*
651      * Spool directory from printcap file.
652      */
653     if ( pr->p_flags & P_SPOOLED ) {
654         if ( pgetent( printcap, buf, pr->p_printer ) != 1 ) {
655             syslog( LOG_ERR, "No such printer: %s", pr->p_printer );
656             return( -1 );
657         }
658
659         /*
660          * Spool directory.
661          */
662         if ( pr->p_spool != NULL && pr->p_spool != defprinter.p_spool ) {
663             free( pr->p_spool );
664         }
665         a = area;
666         if (( p = pgetstr( "sd", &a )) == NULL ) {
667             pr->p_spool = defprinter.p_spool;
668         } else {
669             if (( pr->p_spool = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
670                 syslog( LOG_ERR, "malloc: %m" );
671                 exit( 1 );
672             }
673             strcpy( pr->p_spool, p );
674         }
675
676         /*
677          * Is accounting on?
678          */
679         a = area;
680         if ( pgetstr( "af", &a ) == NULL ) {
681             pr->p_flags &= ~P_ACCOUNT;
682         } else {
683             pr->p_flags |= P_ACCOUNT;
684 #ifdef ABS_PRINT
685             if ( pr->p_role != NULL && pr->p_role != defprinter.p_role ) {
686                 free( pr->p_role );
687             }
688             a = area;
689             if (( p = pgetstr( "ro", &a )) == NULL ) {
690                 pr->p_role = defprinter.p_role;
691             } else {
692                 if (( pr->p_role =
693                         (char *)malloc( strlen( p ) + 1 )) == NULL ) {
694                     syslog( LOG_ERR, "malloc: %m" );
695                     exit( 1 );
696                 }
697                 strcpy( pr->p_role, p );
698             }
699
700             if (( c = pgetnum( "si" )) < 0 ) {
701                 pr->p_srvid = defprinter.p_srvid;
702             } else {
703                 pr->p_srvid = c;
704             }
705 #endif ABS_PRINT
706         }
707
708
709         /*
710          * Cost of printer.
711          */
712         if ( pr->p_pagecost_msg != NULL &&
713                 pr->p_pagecost_msg != defprinter.p_pagecost_msg ) {
714             free( pr->p_pagecost_msg );
715         }
716         a = area;
717         if (( p = pgetstr( "pc", &a )) != NULL ) {
718             if (( pr->p_pagecost_msg =
719                     (char *)malloc( strlen( p ) + 1 )) == NULL ) {
720                 syslog( LOG_ERR, "malloc: %m" );
721                 exit( 1 );
722             }
723             strcpy( pr->p_pagecost_msg, p );
724             pr->p_pagecost = 0;
725         } else if ( pr->p_flags & P_ACCOUNT ) {
726             if (( c = pgetnum( "pc" )) < 0 ) {
727                 pr->p_pagecost = defprinter.p_pagecost;
728             } else {
729                 pr->p_pagecost = c;
730             }
731             pr->p_pagecost_msg = NULL;
732         }
733
734         /*
735          * Get lpd lock file.
736          */
737         if ( pr->p_lock != NULL && pr->p_lock != defprinter.p_lock ) {
738             free( pr->p_lock );
739         }
740         a = area;
741         if (( p = pgetstr( "lo", &a )) == NULL ) {
742             pr->p_lock = defprinter.p_lock;
743         } else {
744             if (( pr->p_lock = (char *)malloc( strlen( p ) + 1 )) == NULL ) {
745                 syslog( LOG_ERR, "malloc: %m" );
746                 exit( 1 );
747             }
748             strcpy( pr->p_lock, p );
749         }
750
751 #ifdef KRB
752         /*
753          * Must Kerberos authenticate?
754          */
755         if ( pgetflag( "ka" ) == 1 ) {
756             pr->p_flags |= P_KRB;
757         } else {
758             pr->p_flags &= ~P_KRB;
759         }
760 #endif
761
762         endprent();
763     }
764
765     return( 0 );
766 }