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