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