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