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