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