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