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