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